目录
本章介绍MySQL支持的SQL语句的语法 。
ALTER {DATABASE | SCHEMA} [ db_name]
alter_specification...
ALTER {DATABASE | SCHEMA}db_name
升级数据目录名称
alter_specification:
[DEFAULT] CHARACTER SET [=] charset_name
| [DEFAULT] COLLATE [=]collation_name
ALTER DATABASE使您可以更改数据库的整体特征。这些特征存储在db.opt数据库目录中的文件中。要使用ALTER
DATABASE,您需要ALTER数据库的
特权。
ALTER
SCHEMA是一个同义词ALTER
DATABASE。
数据库名称可以从第一个语法中省略,在这种情况下,该语句适用于默认数据库。
该CHARACTER SET子句更改默认数据库字符集。该COLLATE子句更改默认数据库排序规则。第10章,字符集,排序规则,Unicode讨论了字符集和排序规则名称。
您可以分别使用SHOW CHARACTER
SET和SHOW COLLATION
语句查看可用的字符集和归类。有关更多信息,请参见第13.7.5.3节“SHOW CHARACTER SET语法”和
第13.7.5.4节“SHOW COLLATION语法”。
如果更改数据库的缺省字符集或排序规则,则必须删除并重新创建使用数据库缺省值的存储例程,以便它们使用新的缺省值。(在存储例程中,如果未明确指定字符集或排序规则,则具有字符数据类型的变量将使用数据库默认值,请参见第13.1.16节“CREATE PROCEDURE和CREATE FUNCTION语法”。)
包含该UPGRADE DATA DIRECTORY
NAME子句的语法更新与数据库关联的目录的名称,以使用MySQL 5.1中实现的编码将数据库名称映射到数据库目录名称(请参见
第9.2.3节“将标识符映射到文件名称”)。本条款适用于以下情况:
它旨在将MySQL从旧版本升级到5.1或更高版本。
如果名称包含需要编码的特殊字符,它旨在将数据库目录名称更新为当前编码格式。
该语句使用mysqlcheck的(通过调用mysql_upgrade)。
例如,如果MySQL 5.0中的数据库具有名称
a-b-c,则名称包含-(破折号)字符的实例
。在MySQL 5.0中,数据库目录也被命名a-b-c,这对于所有文件系统来说都不一定安全。在MySQL 5.1和更高版本中,相同的数据库名称被编码为a@002db@002dc
产生文件系统中立的目录名称。
当MySQL安装从旧版本升级到MySQL 5.1或更高版本时,服务器会显示一个名称(如
a-b-c旧格式)
#mysql50#a-b-c,您必须使用#mysql50#前缀引用该名称。使用
UPGRADE DATA DIRECTORY NAME在这种情况下,明确地告诉服务器数据库目录名称重新编码为当前编码格式:
ALTER DATABASE`#mysql50#abc`升级数据目录名称;
执行此语句后,可以将数据库引用为a-b-c没有特殊
#mysql50#前缀的数据库
。
该UPGRADE DATA DIRECTORY NAME子句在MySQL 5.7.6中被弃用,并且将在未来版本的MySQL中被删除。如果需要转换MySQL 5.0数据库或表名,解决方法是在升级到更新版本之前将MySQL 5.0安装升级到MySQL 5.1。
改变
[DEFINER = { user| 当前用户 }]
事件event_name
[在附表schedule]
[完成[不]保存]
[RENAME TO new_event_name]
[启用| DISABLE | 禁止在奴隶]
[评论' string']
[DO event_body]
该ALTER EVENT语句可以更改现有事件的一个或多个特性,而无需删除和重新创建它。的语法的每个的
DEFINER,ON SCHEDULE,
ON COMPLETION,COMMENT,
ENABLE/ DISABLE,和
DO条款是完全一样的当用于如CREATE EVENT。(请参见
第13.1.12节“CREATE EVENT语法”。)
任何用户都可以更改该用户拥有该EVENT权限的数据库上定义的事件。当用户执行成功的ALTER
EVENT语句时,该用户将成为受影响事件的定义者。
ALTER EVENT 仅适用于现有活动:
的MySQL>ALTER EVENT no_such_event>ON SCHEDULE> ERROR 1517(HY000):未知事件'no_such_event'EVERY '2:3' DAY_HOUR;
在以下每个示例中,假定名为的事件
myevent定义如下所示:
创建事件myevent
按照时间表
每6小时
评论'样本评论'。
做
UPDATE myschema.mytable SET mycol = mycol + 1;
以下声明将时间表myevent从立即开始的每六小时一次更改为
每十二小时一次,从声明运行时间起四小时开始:
ALTER EVENT myevent
按照时间表
每12小时
STARTS CURRENT_TIMESTAMP + INTERVAL 4小时;
可以在单个语句中更改事件的多个特征。本示例将执行的SQL语句更改为myevent删除所有记录的
语句mytable; 它还会更改事件的时间安排,以便在此ALTER EVENT语句运行一天后执行一次
。
ALTER EVENT myevent
按照时间表
AT CURRENT_TIMESTAMP + INTERVAL 1天
做
TRUNCATE TABLE myschema.mytable;
在ALTER
EVENT语句中指定选项仅用于您想要更改的特征; 省略选项保留其现有值。这包括CREATE
EVENT诸如的任何默认值ENABLE。
要禁用myevent,请使用以下
ALTER EVENT语句:
ALTER EVENT myevent
禁用;
该ON SCHEDULE子句可以使用涉及内置MySQL函数和用户变量的表达式来获取它所包含的任何timestamp或
interval值。您不能在这些表达式中使用存储的例程或用户定义的函数,并且不能使用任何表引用; 不过,你可以使用SELECT FROM DUAL。对于两者ALTER EVENT和
CREATE EVENT陈述都是如此
。在这种情况下,对存储例程,用户定义函数和表的引用是不允许的,并且会因错误而失败(请参见错误#22830)。
虽然
在其子句ALTER EVENT中包含另一个ALTER EVENT语句的DO语句似乎成功,但当服务器尝试执行结果的预定事件时,执行失败并显示错误。
要重命名事件,请使用ALTER
EVENT语句的RENAME TO子句。该语句将该事件重命名myevent为
yourevent:
ALTER EVENT myevent
RENAME to yourevent;
您还可以将事件移动到不同的数据库使用
ALTER EVENT ... RENAME TO ...和
表示法,如下所示:
db_name.event_name
ALTER EVENT olddb.myevent
重命名为newdb.myevent;
要执行前面的语句,执行它的用户必须具有对数据库和数据库的EVENT权限
。
olddbnewdb
没有RENAME EVENT声明。
该值DISABLE ON SLAVE用于复制从站而不是ENABLE或
DISABLE指示在主站上创建并复制到从站的事件,但不在从站上执行。通常,DISABLE ON
SLAVE根据需要自动设置; 但是,有些情况下您可能需要或需要手动更改它。有关更多信息,请参见第16.4.1.16节“调用的功能的复制”。
ALTER FUNCTIONfunc_name[characteristic...]characteristic: 评论'string' | 语言SQL | {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA} | SQL安全性{DEFINER | INVOKER}
这个语句可以用来改变存储函数的特性。可以在ALTER FUNCTION声明中指定多个更改
。但是,您不能使用此语句更改存储函数的参数或主体; 要进行这样的更改,您必须使用DROP
FUNCTION和删除并重新创建函数CREATE
FUNCTION。
您必须拥有ALTER ROUTINE
该功能的特权。(该权限自动授予函数创建者。)如果启用了二进制日志记录,则该ALTER FUNCTION
语句可能还需要该
SUPER权限,如
第23.7节“存储程序的二进制日志记录”中所述。
更改实例旋转INNODB主密钥
ALTER INSTANCE,在MySQL 5.7.11中引入,定义了适用于MySQL服务器实例的操作。
该ALTER INSTANCE ROTATE INNODB MASTER KEY
语句用于旋转用于InnoDB表空间加密的主加密密钥
。钥匙圈插件必须加载才能使用此语句。有关密钥环插件的信息,请参见第6.5.4节“MySQL密钥环”。密钥轮换需要SUPER特权。
ALTER INSTANCE ROTATE INNODB MASTER KEY
支持并发DML。但是,它不能同时与运行CREATE TABLE
... ENCRYPTION或
ALTER TABLE ...
ENCRYPTION作业,并采取锁来防止可能与这些陈述的并发执行出现的冲突。如果其中一个冲突语句正在运行,则必须先完成其他语句才能继续。
ALTER INSTANCE 操作被写入到二进制日志中,以便它们可以在复制服务器上执行。
有关其他ALTER INSTANCE ROTATE INNODB MASTER
KEY使用信息,请参见
第14.7.10节“InnoDB表空间加密”。有关密钥环插件的信息,请参见第6.5.4节“MySQL密钥环”。
ALTER LOGFILE GROUPlogfile_groupADD UNDOFILE'file_name' [INITIAL_SIZE [=]size] [等待] ENGINE [=]engine_name
该语句将一个UNDO名为“ file_name' 的文件添加到现有的日志文件组中logfile_group。一个
ALTER LOGFILE GROUP声明只有一个ADD UNDOFILE条款。DROP UNDOFILE目前没有
条款支持。
所有NDB群集磁盘数据对象共享相同的名称空间。这意味着每个磁盘数据对象必须是唯一命名的(而不仅仅是给定类型的每个磁盘数据对象)。例如,不能使用同名的表空间和撤消日志文件,或者具有相同名称的撤消日志文件和数据文件。
可选INITIAL_SIZE参数UNDO以字节为单位设置
文件的初始大小; 如果未指定,则初始大小默认为134217728(128 MB)。您可以选择遵循size一个数量级的单字母缩写,类似于中使用的缩写my.cnf。通常,这是字母M(兆字节)或
G(千兆字节)之一。(错误#13116514,错误#16104705,错误#62858)
在32位系统上,支持的最大值为
INITIAL_SIZE4294967296(4 GB)。(错误#29186)
最小允许值为INITIAL_SIZE1048576(1 MB)。(错误#29574)
WAIT被解析,但被忽略。此关键字目前不起作用,并且用于未来的扩展。
的ENGINE参数(必需)确定这是由该日志文件组所使用的,与存储引擎
engine_name是所述存储引擎的名称。目前,唯一可接受的值
engine_name是
“ NDBCLUSTER”和
“ NDB”。这两个值是等价的。
下面是一个例子,它假定日志文件组
lg_3已经被创建
CREATE LOGFILE GROUP(见
第13.1.15节“CREATE LOGFILE GROUP语法”):
ALTER LOGFILE GROUP lg_3
ADD UNDOFILE'undo_10.dat'
INITIAL_SIZE = 32M
ENGINE = NDBCLUSTER;
当ALTER LOGFILE GROUP与用于ENGINE = NDBCLUSTER(可替换地,
ENGINE = NDB),一个UNDO在每个NDB簇数据节点上创建日志文件。您可以UNDO通过查询INFORMATION_SCHEMA.FILES表来验证文件是否已创建并获取有关它们的信息
。例如:
mysql>SELECT FILE_NAME, LOGFILE_GROUP_NUMBER, EXTRA- >FROM INFORMATION_SCHEMA.FILES- >WHERE LOGFILE_GROUP_NAME = 'lg_3';+ ------------- + ---------------------- + ------------ ---- + | FILE_NAME | LOGFILE_GROUP_NUMBER | EXTRA | + ------------- + ---------------------- + ------------ ---- + | newdata.dat | 0 | CLUSTER_NODE = 3 | | newdata.dat | 0 | CLUSTER_NODE = 4 | | undo_10.dat | 11 | CLUSTER_NODE = 3 | | undo_10.dat | 11 | CLUSTER_NODE = 4 | + ------------- + ---------------------- + ------------ ---- + 4行(0.01秒)
(请参见第24.8节“INFORMATION_SCHEMA文件表”)。
用于存储的内存UNDO_BUFFER_SIZE来自全局池,其大小由SharedGlobalMemory数据节点配置参数的值决定
。这包括通过设置InitialLogFileGroup数据节点配置参数为此选项隐含的任何默认值
。
ALTER LOGFILE GROUP仅适用于NDB群集的磁盘数据存储。有关更多信息,请参见
第21.5.13节“NDB群集磁盘数据表”。
ALTER程序proc_name[characteristic...]characteristic: 评论'string' | 语言SQL | {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA} | SQL安全性{DEFINER | INVOKER}
此语句可用于更改存储过程的特征。可以在ALTER PROCEDURE声明中指定多个更改
。但是,您无法使用此语句更改存储过程的参数或主体; 要进行这样的更改,您必须使用DROP
PROCEDURE和删除并重新创建该过程CREATE
PROCEDURE。
您必须拥有ALTER ROUTINE
该程序的特权。默认情况下,该权限被自动授予过程创建者。这种行为可以通过禁用automatic_sp_privileges系统变量来改变
。请参见第23.2.2节“存储例程和MySQL特权”。
ALTER SERVERserver_nameOPTIONS(option[,option] ...)
更改服务器信息
,调整server_nameCREATE SERVER语句中允许的任何选项
。mysql.servers表中的相应字段会相应更新。该声明需要
SUPER特权。
例如,要更新USER选项:
改变服务器的选项(用户的''';
ALTER SERVER导致隐式提交。请参见
第13.3.3节“导致隐式提交的语句”。
ALTER SERVER 不写入二进制日志,不管正在使用的日志格式如何。
ALTER TABLEtbl_name[alter_specification[,alter_specification] ...] [partition_options]alter_specification:table_options| 添加[COLUMN] [FIRST | 后]col_namecolumn_definitioncol_name| ADD [COLUMN](,...)col_namecolumn_definition| ADD {INDEX | KEY} [index_name] [index_type](index_col_name,...)[index_option] ... | ADD [CONSTRAINT [symbol]] PRIMARY KEY [index_type](index_col_name,...)[index_option] ... | ADD [CONSTRAINT [symbol]] 唯一[INDEX | KEY] [index_name] [index_type](index_col_name,...)[index_option] ... | ADD FULLTEXT [INDEX | KEY] [index_name] (index_col_name,...)[index_option] ... | ADD SPATIAL [INDEX | KEY] [index_name] (index_col_name,...)[index_option] ... | ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name](index_col_name,...)reference_definition| 算法[=] {默认|输入|复制} | ALTER [COLUMN]col_name{SET DEFAULTliteral| DROP DEFAULT} | CHANGE [COLUMN] [FIRST | AFTER ]old_col_namenew_col_namecolumn_definitioncol_name| [DEFAULT]字符集[=]charset_name[COLLATE [=]collation_name] | 转换为字符集charset_name[COLLATEcollation_name] | {禁用|启用}键 | {DISCARD | IMPORT}表空间 | DROP [COLUMN]col_name| DROP {INDEX | KEY}index_name| DROP PRIMARY KEY | 删除外键fk_symbol| 力 | LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE} | MODIFY [COLUMN] [FIRST | 后]col_namecolumn_definitioncol_name| ORDER BYcol_name[,col_name] ... | 重命名{INDEX | KEY}old_index_nameTOnew_index_name| RENAME [TO | AS]new_tbl_name| {无| WITH}验证 | ADD PARTITION(partition_definition) | 删除分区partition_names| DISCARD PARTITION {partition_names| ALL}表空间 | IMPORT PARTITION {partition_names| ALL}表空间 | TRUNCATE PARTITION {partition_names| 所有} | COALESCE PARTITIONnumber| 重组分区partition_namesINTO(partition_definitions) |partition_name使用表tbl_name[{| WITH WITH} VALIDATION] 交换分区 | 分析分区{partition_names| 所有} | 检查分区{partition_names| 所有} | 优化分区{partition_names| 所有} | REBUILD PARTITION {partition_names| 所有} | 修复分区{partition_names| 所有} | 删除分区 | 升级分区index_col_name:col_name[(length)] [ASC | DESC]index_type: 使用{BTREE | HASH}index_option: KEY_BLOCK_SIZE [=]value|index_type| 与PARSERparser_name| 评论'string'table_options:table_option[[,]table_option] ...table_option: AUTO_INCREMENT [=]value| AVG_ROW_LENGTH [=]value| [DEFAULT] CHARACTER SET [=]charset_name| CHECKSUM [=] {0 | 1} | [DEFAULT] COLLATE [=]collation_name| 评论[=]'string' | COMPRESSION [=] {'ZLIB'|'LZ4'|'NONE'} | CONNECTION [=]'connect_string' | {DATA | INDEX} DIRECTORY [=]'absolute path to directory' | DELAY_KEY_WRITE [=] {0 | 1} | ENCRYPTION [=] {'Y'| 'N'} | ENGINE [=]engine_name| INSERT_METHOD [=] {NO | FIRST | LAST} | KEY_BLOCK_SIZE [=]value| MAX_ROWS [=]value| MIN_ROWS [=]value| PACK_KEYS [=] {0 | 1 | 默认} | PASSWORD [=]'string' | ROW_FORMAT [=] {默认|动态|固定|压缩|冗余|精简} | STATS_AUTO_RECALC [=] {DEFAULT | 0 | 1} | STATS_PERSISTENT [=] {DEFAULT | 0 | 1} | STATS_SAMPLE_PAGES [=]value| TABLESPACEtablespace_name[STORAGE {DISK | MEMORY | DEFAULT}] | UNION [=](tbl_name[,tbl_name] ...)partition_options: (见CREATE TABLE选项)
ALTER TABLE改变表格的结构。例如,您可以添加或删除列,创建或销毁索引,更改现有列的类型或重命名列或表本身。您还可以更改特征,例如用于表格或表格评论的存储引擎。
要使用ALTER TABLE,你需要
ALTER,
CREATE和
INSERT权限表。重命名表需要
ALTER和
DROP对旧表,
ALTER,
CREATE,和
INSERT对新表。
在表名之后,指定要进行的更改。如果没有给出,ALTER TABLE
什么都不做。
许多更改的语法类似于CREATE TABLE
声明的条款。column_definition
条款使用相同的语法ADD和
CHANGE作为CREATE
TABLE。有关更多信息,请参见
第13.1.18节“CREATE TABLE语法”。
这个词COLUMN是可选的,可以省略。
多ADD,ALTER,
DROP,和CHANGE条款,允许在一个单一的ALTER
TABLE声明中,用逗号隔开。这是标准SQL的MySQL扩展,它只允许每个ALTER TABLE
语句中的每个子句中的一个。例如,要在单个语句中删除多个列,请执行以下操作:
ALTER TABLE t2 DROP COLUMN c,DROP COLUMN d;
如果存储引擎不支持尝试的
ALTER TABLE操作,则可能会导致警告。这些警告可以用来显示
SHOW WARNINGS。请参见
第13.7.5.40节“SHOW WARNINGS Syntax”。有关故障排除的信息ALTER TABLE,请参见第B.5.6.1节“ALTER TABLE的问题”。
有关生成列的信息,请参见 第13.1.8.3节“ALTER TABLE和Generated Columns”。
有关使用示例,请参见 第13.1.8.4节“ALTER TABLE示例”。
使用mysql_info()C API函数,您可以找出有多少行被复制
ALTER TABLE。请参见
第27.8.7.36节“mysql_info()”。
该ALTER
TABLE声明还有其他几个方面,在本节中的下列主题下进行介绍:
table_options意味着可以在可以使用的一种表选项CREATE
TABLE语句,比如ENGINE,
AUTO_INCREMENT,
AVG_ROW_LENGTH,MAX_ROWS,
ROW_FORMAT,或TABLESPACE。
有关所有表选项的说明,请参见
第13.1.18节“CREATE TABLE语法”。但是,
ALTER TABLE忽略DATA
DIRECTORY并INDEX DIRECTORY以表格形式给出时。ALTER TABLE
只允许它们作为分区选项,并且从MySQL 5.7.17开始,它要求你有FILE
权限。
使用表格选项ALTER
TABLE提供了改变单个表格特征的便捷方式。例如:
如果t1当前不是
InnoDB表格,则此语句将其存储引擎更改为InnoDB:
ALTER TABLE t1 ENGINE = InnoDB;
有关将表切换到InnoDB存储引擎时的注意
事项,请参见第14.8.1.4节“将表从MyISAM转换为InnoDB”。
当您指定一个ENGINE子句时,
ALTER TABLE重建该表。即使表已经有指定的存储引擎,情况也是如此。
在现有的表上
运行会执行一个
“ 空 ”操作,该操作可用于碎片整理表,如
第14.12.4节“碎片整理表”中所述。在桌子上
运行
执行相同的功能。
ALTER
TABLE tbl_name
ENGINE=INNODBInnoDB ALTER
TABLEInnoDBALTER TABLE
tbl_name FORCEInnoDB
ALTER TABLE
并
使用
在线DDL。有关更多信息,请参见
第14.13.1节“在线DDL概述”。
tbl_name
ENGINE=INNODBALTER TABLE
tbl_name FORCE
尝试更改表的存储引擎的结果受所需存储引擎是否可用以及NO_ENGINE_SUBSTITUTION
SQL模式的设置的影响
,如第5.1.8节“服务器SQL模式”中所述。
为防止无意中丢失数据,
ALTER TABLE不能用于将表的存储引擎更改为
MERGE或BLACKHOLE。
要更改InnoDB表以使用压缩的行存储格式:
ALTER TABLE t1 ROW_FORMAT = COMPRESSED;
如果InnoDB启用了表空间加密功能(请参见
第14.7.10节“InnoDB表空间加密”),t1则可以像下面这样启用或禁用加密:
ALTER TABLE t1 ENCRYPTION ='Y'; ALTER TABLE t1 ENCRYPTION ='N';
重置当前自动增量值:
ALTER TABLE t1 AUTO_INCREMENT = 13;
您不能将计数器重置为小于或等于当前正在使用的值。对于这两个
InnoDB和MyISAM,如果该值小于或等于在当前的最大值AUTO_INCREMENT列中,值被复位为当前最大AUTO_INCREMENT
列值加一。
要更改默认表字符集:
ALTER TABLE t1 CHARACTER SET = utf8;
另请参阅更改字符集。
要添加(或更改)表格评论:
ALTER TABLE t1 COMMENT ='新表评论';
使用ALTER TABLE该
TABLESPACE选项可以InnoDB在现有常规表空间,
文件每表表
空间和
系统表空间之间移动非分区
表
。请参阅
使用ALTER TABLE在表空间之间移动非分区表。
对于分区表,只修改默认表空间。它不会将分区从一个表空间移动到另一个表空间。要移动表分区,您必须使用移动每个分区
。请参阅
使用ALTER TABLE在表空间之间移动表分区。
ALTER TABLE tbl_name
TABLESPACE [=]
tablespace_nameALTER TABLE tbl_name
REORGANIZE PARTITION
ALTER TABLE ... TABLESPACE操作始终会导致完整的表重建,即使该
TABLESPACE属性尚未从其先前的值更改。
ALTER TABLE ... TABLESPACE 语法不支持将表从临时表空间移动到持久表空间。
DATA DIRECTORY受支持
的子句
CREATE TABLE
... TABLESPACE不受支持
ALTER TABLE ... TABLESPACE,并且如果指定则被忽略。
有关该TABLESPACE选件的功能和限制的更多信息,请参阅CREATE TABLE。
MySQL NDB Cluster 7.5.2及更高版本支持设置
NDB_TABLE选项以控制表的分区平衡(片段计数类型),读取任何副本功能,完全复制或这些的任意组合,作为ALTER TABLE语句表注释的一部分
以相同的方式作为用于CREATE TABLE,如本例所示:
ALTER TABLE t1 COMMENT =“NDB_TABLE = READ_BACKUP = 0,PARTITION_BALANCE = FOR_RA_BY_NODE”;
请记住,ALTER TABLE ... COMMENT
...放弃对表格的任何现有评论。有关更多信息和示例,请参阅
设置NDB_TABLE选项。
要验证表格选项是否按预期进行了更改,请使用
SHOW CREATE TABLE或查询
INFORMATION_SCHEMA.TABLES表格。
一些ALTER TABLE操作可以在没有临时副本的情况下执行。就地操作往往非常快。
其他ALTER TABLE操作会在表的临时副本上执行更改,这可能需要更多时间,特别是对于大型表。
ALTER TABLE不需要创建原始表的临时副本的
就地操作包括:
ALTER TABLE对在线DDL功能InnoDB支持的表进行
操作
。有关支持的操作的概述,请参见
第14.13.1节“在线DDL概述”。有关在线DDL操作的性能和并发性的信息,请参见
第14.13.2节“在线DDL性能,并发和空间要求”。
InnoDB
ALTER TABLE 。在没有其他选项的情况下运行时,MySQL会重命名与该表对应的文件,tbl_name
RENAME TO new_tbl_nametbl_name
而不进行复制。(您也可以使用该
RENAME TABLE语句来重命名表,请参见第13.1.33节“RENAME TABLE语法”)。专用于重命名表的权限不会迁移到新名称。他们必须手动更改。
只修改表格元数据而不修改表格数据的更改是即时的,因为服务器只需要更改表格
.frm文件,而不是触摸表格内容。以下方式进行了以下更改:
重命名索引。
添加或删除索引,for
InnoDB和
NDB。请参见
第14.13.1节“在线DDL概述”。
对于NDB表,在可变宽度列上添加和删除索引的操作可以在线进行,无需复制表格,也不会在大多数持续时间内阻止并发DML操作。请参见
第13.1.8.2节“NDB集群中的ALTER TABLE联机操作”。
指定ALGORITHM=INPLACE使操作对支持它的子句和存储引擎使用就地技术,否则将失败并返回错误,从而避免冗长的表副本,如果尝试更改使用不同于您的预期的存储引擎的表。
ALTER TABLE没有就地执行的操作会
创建原始表的临时副本。MySQL等待修改表的其他操作,然后继续。它将修改合并到副本中,删除原始表并重命名新的表。在ALTER
TABLE执行时,原始表格可以被其他会话读取(很快会有例外)。更新并写入到在表之后开始的表
ALTER TABLE操作开始将停止,直到新表准备就绪,然后自动重定向到新表,而不会有任何失败的更新。原始表的临时副本在新表的数据库目录中创建。对于ALTER
TABLE将表重命名为不同数据库的操作,这可能与原始表的数据库目录不同。
前面提到的例外情况是,
ALTER TABLE块准备安装新版本的表.frm文件,放弃旧文件并清除表和表定义缓存中的过期表结构,从而读取(不只是写入)块。此时,它必须获得排他锁。为此,它等待当前阅读器完成,并阻止新的读取(和写入)。
对于MyISAM表格,可以通过将myisam_sort_buffer_size系统变量设置为较高值来加快索引重新创建(变更过程中最慢的部分)
。
对于InnoDB表,ALTER TABLE驻留在共享表空间(如常规表空间
或系统表空间)中的表上的表复制
操作
可以增加表空间使用的空间量。这些操作需要与表中的数据和索引一样多的额外空间。对于驻留在共享表空间中的表而言,在表复制ALTER TABLE操作期间使用的额外空间不会释放回操作系统,因为它适用于驻留在每个表的
文件表
空间中的表。
要强制将表格复制方法用于ALTER
TABLE不使用它的操作,请将old_alter_table系统变量设置为
ON或指定
ALGORITHM=COPY为其中一个
alter_specification子句。如果old_alter_table
设置与一个ALGORITHM不同于其他值的子句之间存在冲突DEFAULT,则该
ALGORITHM子句优先。
指定ALGORITHM=DEFAULT与根本不指定任何ALGORITHM子句相同,在ALGORITHM=INPLACE存储引擎支持的情况下使用这种情况。否则,ALGORITHM=COPY
使用。
ALTER TABLE使用该ALGORITHM=COPY子句运行
的操作可防止并发的DML操作。并发查询仍然是允许的。也就是说,表复制操作总是至少包含并发限制LOCK=SHARED(允许查询但不包括DML)。您可以通过指定LOCK=EXCLUSIVE阻止DML和查询来进一步限制这些操作的并发性。
ALTER TABLE升级的MySQL 5.5的时间列到5.6格式ADD COLUMN,
CHANGE COLUMN,MODIFY
COLUMN,ADD INDEX,和
FORCE操作。这种转换不能用INPLACE算法完成,因为表格必须重建,所以ALGORITHM=INPLACE在这些情况下指定会
导致错误。ALGORITHM=COPY如有必要指定。
如果ALTER TABLE对用于通过KEY更改列顺序对表进行分区的多列索引进行的操作,则只能使用该操作执行
ALGORITHM=COPY。
该WITHOUT VALIDATION和WITH
VALIDATION子句会影响是否
ALTER TABLE对虚拟生成的列修改执行就地操作
。请参见
第13.1.8.3节“ALTER TABLE和Generated Columns”。
NDB集群以前ALTER
TABLE使用ONLINE和
OFFLINE关键字支持在线操作。这些关键字不再受支持; 它们的使用导致语法错误。MySQL NDB Cluster 7.5(及更高版本)支持ALGORITHM=INPLACE使用与标准MySQL服务器使用相同语法的在线操作
。有关更多信息,请参见第13.1.8.2节“NDB集群中的ALTER TABLE联机操作”。
ALTER TABLE与DISCARD ... PARTITION
... TABLESPACE或IMPORT ... PARTITION ...
TABLESPACE不创建任何临时表或临时分区文件。
ALTER TABLE与ADD
PARTITION,DROP PARTITION,
COALESCE PARTITION,REBUILD
PARTITION,或REORGANIZE PARTITION
不创建的临时表(当用于除了
NDB表); 但是,这些操作可以并且确实会创建临时分区文件。
ADD或DROP操作
RANGE或LIST分区是即时操作或几乎如此。ADD或
COALESCE操作HASH
或KEY分区在所有分区之间复制数据,除非LINEAR HASH或被
LINEAR KEY使用; 这是有效地与创建一个新的表,虽然ADD
或COALESCE操作由分区执行的分区。REORGANIZE操作只复制更改的分区,不要触摸不变的分区。
要控制表格在并发读写时的级别,请使用该LOCK
子句。为此子句指定非默认值使您可以在alter操作期间要求一定数量的并发访问权限或排他性权限,并且如果请求的锁定级别不可用,则会暂停操作。该LOCK子句的参数是:
LOCK = DEFAULT
给定ALGORITHM子句(如果有)和
ALTER TABLE操作的最大并发级别
:允许并发读写(如果支持)。如果不支持,则允许并行读取。如果不是,则强制执行独占访问。
LOCK = NONE
如果支持,则允许并发读取和写入。否则,会发生错误。
LOCK = SHARED
如果支持,则允许并发读取但阻止写入。即使存储引擎支持给定ALGORITHM
子句(如果有)和ALTER TABLE操作的并发写入,写入也会被阻止。如果不支持并发读取,则会发生错误。
LOCK = EXCLUSIVE
强制独占访问。即使存储引擎支持给定ALGORITHM子句(如果有)和
ALTER TABLE操作的并发读写,也会执行此
操作。
用于ADD向表中添加新列,并
DROP删除现有列。
DROP 是标准SQL的MySQL扩展。
col_name
要在表格行中的特定位置添加列,请使用
FIRST或。默认是最后添加列。
AFTER
col_name
如果一个表只包含一列,则该列不能被删除。如果您打算删除该表,请改用该
DROP TABLE语句。
如果从表中删除列,则列也将从它们所属的任何索引中删除。如果组成索引的所有列都被删除,那么索引也会被删除。
该CHANGE,MODIFY和
ALTER子句可以改变现有列的名称和定义。他们有这些比较特征:
CHANGE:
可以重命名列并更改其定义,或两者都可以。
具有更多的能力MODIFY,但是以某些操作的便利为代价。
CHANGE如果不重命名,则需要命名该列两次。
使用FIRSTor AFTER,可以重新排列列。
MODIFY:
可以更改列定义,但不能更改其名称。
比CHANGE改变列定义而不重命名更方便。
使用FIRSTor AFTER,可以重新排列列。
ALTER:仅用于更改列默认值。
CHANGE是标准SQL的MySQL扩展。
MODIFY是Oracle兼容性的MySQL扩展。
要更改列以更改其名称和定义,请使用
CHANGE指定新名称和新定义的名称。例如,要将INT NOT
NULL列重命名a为
b并更改其定义以BIGINT在保留NOT NULL属性的同时使用
数据类型
,请执行以下操作:
ALTER TABLE t1 CHANGE ab BIGINT NOT NULL;
要更改列定义但不更改其名称,请使用
CHANGE或MODIFY。使用时
CHANGE,语法需要两个列名,所以您必须指定相同的名称两次以保持名称不变。例如,要更改列的定义
b,请执行以下操作:
ALTER TABLE t1 CHANGE bb INT NOT NULL;
MODIFY 更改定义而不更改名称更方便,因为它只需要一次列名称:
ALTER TABLE t1 MODIFY b INT NOT NULL;
要更改列名称而不是其定义,请使用
CHANGE。该语法需要列定义,因此要保持定义不变,您必须重新指定列当前具有的定义。例如,要将INT NOT NULL列
重命名b为a,请执行以下操作:
ALTER TABLE t1 CHANGE ba INT NOT NULL;
对于使用CHANGEor的
列定义更改MODIFY,定义必须包括数据类型以及应用于新列的所有属性,而不是索引属性(如PRIMARY KEYor)
UNIQUE。原始定义中存在但未为新定义指定的属性不会继续执行。假设列col1被定义为,INT UNSIGNED DEFAULT 1 COMMENT 'my
column'并且您按如下方式修改该列,意图仅更改INT为
BIGINT:
ALTER TABLE t1 MODIFY col1 BIGINT;
这种说法从改变数据类型INT
来BIGINT,但它也下降了
UNSIGNED,DEFAULT和
COMMENT属性。要保留它们,声明必须明确地包含它们:
ALTER TABLE t1 MODIFY col1 BIGINT UNSIGNED DEFAULT 1 COMMENT'my column';
对于使用CHANGEor的
数据类型更改MODIFY,MySQL会尝试尽可能将现有列值转换为新类型。
此转换可能会导致数据更改。例如,如果缩短字符串列,则值可能会被截断。如果转换为新数据类型会导致数据丢失,要防止操作成功,ALTER TABLE请在使用前启用严格SQL模式(请参见
第5.1.8节“服务器SQL模式”)。
如果使用CHANGE或MODIFY
缩短列上存在索引的列,并且结果列长度小于索引长度,则MySQL会自动缩短索引。
对于CHANGE重命名的列,MySQL会自动将这些引用重命名为已重命名的列:
引用旧列的索引,包括索引和禁用MyISAM索引。
指向旧列的外键。
对于重命名的列CHANGE,MySQL不会自动将这些引用重命名为重命名列:
生成引用重命名列的列和分区表达式。您必须使用CHANGE重新定义与ALTER TABLE重命名该列的语句相同的
语句。
视图和存储的程序引用了重命名的列。您必须手动更改这些对象的定义以引用新的列名称。
要对表格中的列重新排序,请使用FIRST
和AFTER输入CHANGE或
MODIFY操作。
ALTER ... SET DEFAULT或ALTER ...
DROP DEFAULT为列指定新的默认值或分别删除旧的默认值。如果删除旧的默认值并且该列可以NULL,则新的默认值为NULL。如果该列不可用
NULL,MySQL将按照第11.7节“数据类型默认值”中所述分配默认值。
DROP PRIMARY KEY删除
主键。如果没有主键,则会发生错误。有关主键(尤其是InnoDB表)的性能特征的信息
,请参见
第8.3.2节“主键优化”。
如果你添加一个UNIQUE INDEX或者PRIMARY
KEY一个表格,MySQL会在任何非唯一索引之前存储它,以便尽可能早地检测到重复键值。
DROP INDEX删除索引。这是标准SQL的MySQL扩展。请参见
第13.1.25节“DROP INDEX语法”。要确定索引名称,请使用
。
SHOW INDEX FROM
tbl_name
某些存储引擎允许您在创建索引时指定索引类型。index_type说明符的语法
是。有关详细信息
,请参见第13.1.14节“CREATE INDEX语法”。首选位置在列表之后。支持在列列表之前使用该选项将在未来的MySQL版本中被删除。
USING
type_nameUSING
index_option值指定了索引的其他选项。有关允许index_option值的详细信息
,请参见
第13.1.14节“CREATE INDEX语法”。
RENAME INDEX 重新命名一个索引。这是标准SQL的MySQL扩展。表格的内容保持不变。
old_index_name TO
new_index_nameold_index_name必须是表中不存在相同ALTER TABLE语句的现有索引的名称
。
new_index_name是新的索引名称,在应用更改后,它不能在结果表中复制索引的名称。索引名称都不是
PRIMARY。
如果您ALTER TABLE在MyISAM表格上使用
,则所有非唯一索引都将在单独的批次中创建(如下REPAIR
TABLE)。ALTER
TABLE当你有很多索引时,这应该会更快。
对于MyISAM表格,可以明确控制密钥更新。使用ALTER TABLE ... DISABLE
KEYS要告诉MySQL停止更新非唯一索引。然后使用ALTER TABLE ... ENABLE KEYS重新创建缺少的索引。MyISAM用一种比逐个插入密钥要快得多的特殊算法来实现这一点,因此在执行批量插入操作之前禁用密钥应该会带来相当大的加速。除了前面提到ALTER TABLE ... DISABLE KEYS的INDEX权限之外,使用还
需要
特权。
虽然非唯一索引是禁用的,但它们会被忽略,例如SELECT和
EXPLAIN否则会使用它们的语句。
在ALTER TABLE声明之后,可能需要运行ANALYZE
TABLE以更新索引基数信息。请参见
第13.7.5.22节“SHOW INDEX语法”。
在FOREIGN KEY和
REFERENCES条款由支持
InnoDB和NDB存储引擎,它实现。请参见第1.8.3.2节“FOREIGN KEY约束” ; 有关特定信息,请参见
第14.8.1.6节“InnoDB和FOREIGN KEY约束”。
ADD [CONSTRAINT
[symbol]] FOREIGN KEY
[index_name] (...) REFERENCES ...
(...)InnoDB
对于其他存储引擎,子句将被解析但被忽略。该
CHECK子句已解析,但被所有存储引擎忽略。请参见第13.1.18节“CREATE TABLE语法”。接受但忽略语法子句的原因是为了兼容性,使其更容易从其他SQL服务器移植代码,并运行使用引用创建表的应用程序。请参见
第1.8.2节“MySQL与标准SQL的差异”。
对于ALTER TABLE不像
CREATE TABLE,ADD FOREIGN
KEY忽略了index_name如果给,并使用自动生成的外键的名称。作为解决方法,请包含CONSTRAINT用于指定外键名称的子句:
ADD CONSTRAINT nameFOREIGN KEY(....)...
MySQL默默地忽略内联REFERENCES
规范,其中引用被定义为列规范的一部分。MySQL只接受
REFERENCES定义为单独FOREIGN KEY规范一部分的子句。
分区InnoDB表不支持外键。此限制不适用于
NDB表格,包括通过明确分区的表格[LINEAR] KEY。有关更多信息,请参见
第22.6.2节“与存储引擎相关的分区限制”。
MySQL服务器和NDB集群都支持使用
ALTER TABLE删除外键:
ALTER TABLEtbl_nameDROP FOREIGN KEYfk_symbol;
在同一ALTER TABLE语句中添加和删除外键
支持ALTER TABLE ...
ALGORITHM=INPLACE但不支持
ALTER TABLE ...
ALGORITHM=COPY。
服务器禁止更改可能导致引用完整性丢失的外键列。它还禁止更改可能不安全的列的数据类型。例如,改变
VARCHAR(20)到
VARCHAR(30)是允许的,但改变它VARCHAR(1024)不是因为其改变来存储单个值所需的长度的字节数。解决方法是
ALTER TABLE ... DROP
FOREIGN KEY在更改列定义之前和
ALTER TABLE ... ADD
FOREIGN KEY之后使用。
ALTER TABLE 更改内部生成的外键约束名称和包含字符串“ tbl_name RENAME
new_tbl_nametbl_name_ibfk_ ”以反映新表名称的用户定义外键约束名称
。InnoDB将包含字符串“ tbl_name_ibfk_ ”的外键约束名称解释
为内部生成的名称。
要更改默认的表字符集和所有字符列(CHAR,
VARCHAR,
TEXT)到一个新的字符集,使用这样的语句:
改变表tbl_name转换为字符集charset_name;
该语句还会更改所有字符列的排序规则。如果您指定no COLLATE子句来指示要使用哪种归类,则该语句将使用字符集的默认归类。如果此归类对于预期的表使用不合适(例如,如果它将从区分大小写的归类更改为不区分大小写的归类),请明确指定归类。
对于具有的数据类型的列
VARCHAR或一个
TEXT种类,CONVERT TO
CHARACTER SET改变了数据类型必须确保新列足够长,以尽可能多的字符存储为原始列。例如,一
TEXT列有两个长度字节,它们存储列中字节长度的值,最大值为65,535。对于一latin1
TEXT列,每个字符需要一个字节,所以该列最多可以存储65,535个字符。如果列转换为utf8,则每个字符最多可能需要三个字节,最大可能长度为3×65,535 = 196,605个字节。该长度不适合TEXT列的长度字节,所以MySQL将数据类型转换为
MEDIUMTEXT,它是长度字节可记录196,605的最小字符串类型。同样,一VARCHAR
列可能会转换为
MEDIUMTEXT。
为了避免上述类型的数据类型更改,请勿使用
CONVERT TO CHARACTER SET。而是
MODIFY用于更改单个列。例如:
ALTER TABLE t MODIFY latin1_text_col TEXT CHARACTER SET utf8;
ALTER TABLE t MODIFY latin1_varchar_col VARCHAR(M)CHARACTER SET utf8;
如果您指定CONVERT TO CHARACTER SET binary的CHAR,
VARCHAR和
TEXT列转换为它们相应的二进制字符串类型(BINARY,
VARBINARY,
BLOB)。这意味着列不再具有字符集属性,并且后续
CONVERT TO操作不适用于它们。
如果charset_name是
DEFAULT在一个CONVERT TO CHARACTER
SET操作中,由命名的字符集
character_set_database被用于系统变量。
该CONVERT TO操作转换原始字符集和命名字符集之间的列值。这
不是你想要的,如果你有一个字符集(像latin1)列,但存储的值实际上使用其他一些不兼容的字符集(如utf8)。在这种情况下,您必须为每个这样的列执行以下操作:
ALTER TABLE t1 CHANGE c1 c1 BLOB; ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;
这个工作的原因是,当你转换为BLOB列或从列转换时没有转换。
要仅更改表格的默认字符集,请使用以下语句:
ALTER TABLEtbl_nameDEFAULT CHARACTER SETcharset_name;
这个词DEFAULT是可选的。默认字符集是如果您未为稍后添加到表中的列指定字符集时使用的字符集(例如,with ALTER TABLE ... ADD
column)。
当foreign_key_checks
系统变量启用,这是默认设置,字符集转换是不允许的,其中包括在一个外键约束使用的字符串列的表。解决方法是foreign_key_checks在执行字符集转换之前禁用
。在重新启用之前,您必须在涉及外键约束的两个表上执行转换
foreign_key_checks。如果您foreign_key_checks
仅转换其中一个表后重新启用,
由于在这些操作期间发生的隐式转换(错误#45290,错误#74816),操作ON DELETE
CASCADE或ON UPDATE CASCADE操作可能会破坏引用表中的数据。
一个InnoDB在自己创建的表
文件的每个表的
表空间可以被丢弃,并使用进口
DISCARD TABLESPACE和IMPORT
TABLESPACE选项。这些选项可用于从备份中导入每个文件表空间的表空间,或者将每个文件表的表空间从一个数据库服务器复制到另一个数据库服务器。请参见
第14.7.6节“将文件 - 表 - 表空间复制到另一个实例”。
ORDER BY使您可以按特定顺序创建具有行的新表。此选项主要用于知道您在大多数时间以特定顺序查询行时的情况。在对表格进行重大更改后使用此选项,您可能会获得更高的性能。在某些情况下,如果表格按您希望稍后订购的列顺序排列,则可能会使MySQL的排序更容易。
插入和删除后,表格不会保持指定的顺序。
ORDER BY语法允许指定一个或多个列名进行排序,每个列名分别可选择跟随ASC或DESC分别指示升序或降序排序。默认值是升序。只有列名可以作为排序标准; 任意表达式是不允许的。这个条款应该在任何其他条款之后给出。
ORDER BY对InnoDB表格没有意义,
因为InnoDB
总是根据聚集索引对表格行进行排序
。
在分区表上使用时,ALTER TABLE ... ORDER
BY仅对每个分区中的行进行排序。
partition_options 表示可以与分区表一起使用的选项,用于重新分区,添加,删除,放弃,导入,合并和拆分分区以及执行分区维护。
一条ALTER TABLE
语句可能包含一个PARTITION BY或
REMOVE PARTITIONING其他更改规范的附加条款,但必须在任何其他规范之后最后指定PARTITION
BYor REMOVE PARTITIONING子句。的ADD
PARTITION,DROP PARTITION,
DISCARD PARTITION,IMPORT
PARTITION,COALESCE PARTITION,
REORGANIZE PARTITION,EXCHANGE
PARTITION,ANALYZE PARTITION,
CHECK PARTITION,和REPAIR
PARTITION选项不能与其他单一更改规格组合ALTER TABLE,因为选择刚上市就单个分区的行为。
有关分区选项的更多信息,请参见
第13.1.18节“CREATE TABLE语法”和
第13.1.8.1节“ALTER TABLE分区操作”。有关ALTER TABLE ...
EXCHANGE PARTITION语句的信息和示例,请参见
第22.3.3节“与表交换分区和子分区”。
在MySQL 5.7.6之前,分区InnoDB表使用ha_partition由MyISAM其他存储引擎使用的通用分区处理程序,而不提供它们自己的分区处理程序; 在MySQL 5.7.6及更高版本中,这些表是使用
InnoDB存储引擎自己的(或
“ 本地 ”)分区处理程序创建的。从MySQL 5.7.9开始,您可以使用InnoDBMySQL 5.7.6或更低版本(即,使用创建的ha_partition)将创建的表
升级到本InnoDB
机分区处理程序ALTER TABLE ... UPGRADE
PARTITIONING。(错误#76734,错误#20727344)此
ALTER TABLE语法不接受任何其他选项,并且一次只能在单个表上使用。你也可以使用MySQL 5.7.9或更高版本中的 mysql_upgrade将较旧的分区 InnoDB表升级到本地分区处理程序。
与分区相关的子句ALTER
TABLE可以与分区表一起使用,用于重新分区,添加,删除,放弃,导入,合并和拆分分区以及执行分区维护。
简单地在分区表上使用partition_options
子句ALTER TABLE根据由.de定义的分区方案重新分区表
partition_options。该子句始终以PARTITION BY语法和其他规则适用于
partition_options子句为
前缀CREATE TABLE(有关更多详细信息,请参见第13.1.18节“CREATE TABLE语法”),并且还可用于对现有表进行分区尚未分区。例如,考虑如下所示定义的(未分区的)表格:
CREATE TABLE t1(
id INT,
year_col INT
);
通过HASH使用该id列作为分区键,可以通过以下语句将此表分区为8个分区:
ALTER TABLE t1
PARTITION BY HASH(id)
分区8;
MySQL支持一个ALGORITHM选项
[SUB]PARTITION BY [LINEAR] KEY。
ALGORITHM=1导致服务器在计算分区中行的位置时使用与MySQL 5.1相同的密钥哈希函数;
ALGORITHM=2意味着服务器KEY在MySQL 5.5和更高版本中使用默认实现和使用的新分区表的键哈希函数。(使用MySQL 5.5及更高版本中使用的密钥散列函数创建的分区表不能用于MySQL 5.1服务器。)不指定该选项与使用该选项具有相同的效果ALGORITHM=2。此选项主要用于升级或降级时[LINEAR] KEYMySQL的5.1和更高的MySQL版本之间分配表,或者用于创建由分区表KEY或
LINEAR KEY可以一个MySQL 5.1服务器上使用一个MySQL 5.5或更高版本的服务器上。
要升级KEY在MySQL 5.1中创建的分区表,请首先执行
SHOW CREATE TABLE并记下显示的确切列和分区数。现在ALTER TABLE使用与语句中完全相同的列表和分区数量来执行CREATE TABLE语句,并ALGORITHM=2在PARTITION BY关键字之后立即
添加
。(LINEAR如果用于原始表定义,还应该包含该关键字。)来自mysql客户端中会话的示例如下所示:
MySQL的>SHOW CREATE TABLE p\G*************************** 1. row ******************** ******* 表:p 创建表:CREATE TABLE`p`( `id` int(11)NOT NULL AUTO_INCREMENT, `cd` datetime NOT NULL, PRIMARY KEY(`id`) )ENGINE = InnoDB DEFAULT CHARSET = latin1 / *!50100 PARTITION BY LINEAR KEY(id) 分区32 * / 一排(0.00秒) mysql> PARTITION BY LINEAR KEY ALGORITHM = 2(id)PARTITIONS 32ALTER TABLE p;查询OK,0行受影响(5.34秒) 记录:0重复:0警告:0 MySQL的>SHOW CREATE TABLE p\G*************************** 1. row ******************** ******* 表:p 创建表:CREATE TABLE`p`( `id` int(11)NOT NULL AUTO_INCREMENT, `cd` datetime NOT NULL, PRIMARY KEY(`id`) )ENGINE = InnoDB DEFAULT CHARSET = latin1 / *!50100 PARTITION BY LINEAR KEY(id) 分区32 * / 一排(0.00秒)
降级使用MySQL 5.5及更高版本中使用的默认密钥哈希创建的表以使MySQL 5.1服务器能够使用ALGORITHM=1该表是类似的,除非在这种情况下,您应该使用
MySQL 5.1密钥哈希来强制重建表的分区功能。除了需要与MySQL 5.1服务器兼容之外,建议您不要这样做,因为KEY默认情况下在MySQL 5.5和更高版本中使用的改进的散列函数提供了对旧版实现中发现的一些问题的修复。
借助于升级的表格ALTER TABLE ...
PARTITION BY ALGORITHM=2 [LINEAR] KEY ...不能再被MySQL 5.1服务器使用。(这样的表格需要ALTER TABLE ...
PARTITION BY ALGORITHM=1 [LINEAR] KEY ...在MySQL 5.1服务器再次使用之前降级。)
使用ALTER TABLE
... PARTITION BY语句产生的表必须遵循与使用创建的规则相同的规则CREATE TABLE ...
PARTITION BY。这包括管理表可能具有的任何唯一键(包括任何主键)与分区表达式中使用的列或列之间的关系的规则,如
第22.6.1节“分区键,主键和独特钥匙“。CREATE TABLE ... PARTITION BY指定分区数量的规则也适用于
ALTER TABLE ... PARTITION BY。
该partition_definition子句ALTER TABLE ADD PARTITION支持与该语句的同名子句相同的选项
CREATE TABLE。(有关语法和描述,请参见
第13.1.18节“CREATE TABLE语法”。)假设您已创建分区表,如下所示:
CREATE TABLE t1(
id INT,
year_col INT
)
按范围划分(year_col)(
PARTITION p0值小于(1991),
PARTITION p1值小于(1995),
分区p2值小于(1999)
);
您可以将新分区添加p3到此表中,以存储小于以下值2002
:
ALTER TABLE t1 ADD PARTITION(PARTITION p3 VALUES THAIL(2002));
ADD PARTITION也可以与该TABLESPACE子句一起使用,
以将新分区添加到现有的常规表空间,文件每表表空间或系统表空间。
ALTER TABLE t1 ADD PARTITION
(PARTITION p4的值小于(2015)TABLESPACE =`ts1`);
ALTER TABLE t1 ADD PARTITION
(PARTITION p4的值小于(2015)TABLESPACE =`innodb_file_per_table`);
ALTER TABLE t1 ADD PARTITION
(PARTITION p4的值小于(2015)TABLESPACE =`innodb_system`);
如果该
选项未定义,则该
操作会将该分区添加到表的默认表空间中,该表空间可以在or 期间在表级指定。
TABLESPACE =
tablespace_nameALTER TABLE
... ADD PARTITIONCREATE
TABLEALTER
TABLE
DROP PARTITION可以用来放置一个或多个RANGE或LIST
分区。这种说法不能使用
HASH或KEY
分区; 相反,使用COALESCE
PARTITION(见下文)。存储在partition_names列表中命名的丢弃分区中的任何数据都将被
丢弃。例如,给定t1之前定义的表
,您可以删除名为的分区p0,
p1如下所示:
ALTER TABLE t1 DROP PARTITION p0,p1;
DROP PARTITION不适用于使用NDB
存储引擎的表。请参见
第22.3.1节“RANGE和LIST分区的管理”和
第21.1.6节“NDB集群的已知限制”。
ADD PARTITION并且DROP
PARTITION目前不支持IF
[NOT] EXISTS。
DISCARD
PARTITION ... TABLESPACE并且
IMPORT
PARTITION ... TABLESPACE选项将可传输表空间功能扩展
到单独的
InnoDB表分区。每个
InnoDB表分区都有自己的表空间文件(.idb文件)。可
移动表空间功能可以轻松地将表空间从正在运行的MySQL服务器实例复制到另一个正在运行的实例,或者在同一实例上执行还原。这两个选项都包含一个或多个以逗号分隔的分区名称的列表。例如:
ALTER TABLE t1 DISCARD PARTITION p2,p3 TABLESPACE;
ALTER TABLE t1 IMPORT PARTITION p2,p3 TABLESPACE;
在运行时
DISCARD
PARTITION ... TABLESPACE和
IMPORT
PARTITION ... TABLESPACE子分区表上,分区名称和子分区名称都是允许的。当指定分区名称时,将包含该分区的子分区。
可
移动表空间功能还支持复制或恢复分区InnoDB表(所有分区一次)。有关可传输表空间功能的附加信息
,请参见
第14.7.6节“将文件 - 表 - 表空间复制到另一个实例”。有关使用示例,请参见
第14.7.6.1节“可传输的表空间示例”。
支持重命名分区表。您可以使用间接重命名单个分区ALTER TABLE
... REORGANIZE PARTITION; 但是,此操作会复制分区的数据。
要从选定的分区中删除行,请使用该
TRUNCATE PARTITION选项。该选项采用逗号分隔的一个或多个分区名称列表。例如,考虑t1这里定义的表格:
CREATE TABLE t1(
id INT,
year_col INT
)
按范围划分(year_col)(
PARTITION p0值小于(1991),
PARTITION p1值小于(1995),
分区p2小于(1999),
分区p3值小于(2003),
分区p4值小于(2007)
);
要从分区中删除所有行p0,请使用以下语句:
ALTER TABLE t1 TRUNCATE PARTITION p0;
刚刚显示的声明与以下DELETE声明具有相同的效果:
DELETE FROM t1 WHERE year_col <1991;
在截断多个分区时,分区不必是连续的:这可以极大地简化对分区表的删除操作,否则,WHERE如果使用DELETE语句完成这些操作,则会需要非常复杂的条件。例如,该语句删除分区中的所有行,
p1并p3:
ALTER TABLE t1 TRUNCATE PARTITION p1,p3;
DELETE
这里显示了
一个等效的语句:
从t1处删除WHERE
(year_col> = 1991 AND year_col <1995)
要么
(year_col> = 2003 AND year_col <2007);
如果您使用ALL关键字代替分区名称列表,则该语句将作用于所有表分区。
TRUNCATE PARTITION仅删除行; 它不会改变表本身或其任何分区的定义。
要验证这些行是否已被删除,请INFORMATION_SCHEMA.PARTITIONS使用如下所示的查询来检查该
表:
SELECT PARTITION_NAME,TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME ='t1';
TRUNCATE PARTITION仅适用于使用的分区表支持
MyISAM,
InnoDB或
MEMORY存储引擎。它也适用于BLACKHOLE表格(但不起作用)。它不支持
ARCHIVE表格。
COALESCE PARTITION可以与分区的表一起使用,HASH或
KEY通过减少分区的数量来使用
number。假设你已经创建t2了如下表格:
CREATE TABLE t2(
名称VARCHAR(30),
开始DATE
)
HASH分区(年份(开始))
分区6;
要将分区数
t2从6减少到4,请使用以下语句:
ALTER TABLE t2 COALESCE PARTITION 2;
包含在最后number分区中的数据
将被合并到其余分区中。在这种情况下,分区4和5将合并到前4个分区中(分区编号为0,1,2和3)。
要更改分区表使用的一些但不是全部分区,可以使用REORGANIZE
PARTITION。这种说法可以用几种方式使用:
将一组分区合并到一个分区中。这是通过命名partition_names列表中的几个分区
并提供单个定义来完成的
partition_definition。
将现有分区拆分为多个分区。通过命名单个分区partition_names并提供多个
分区来实现这一点
partition_definitions。
更改使用定义的分区子集的范围VALUES LESS THAN或使用定义的分区子集的值列表
VALUES IN。
将分区从一个表空间移动到另一个表空间。有关示例,请参阅 使用ALTER TABLE移动表空间之间的表分区。
此声明也可以在没有
使用分区自动分区的表的选项的情况下
使用,以强制重新分配数据。(目前,只有这些
表是以这种方式自动分区的。)这在NDB集群中非常有用,在将新的NDB集群数据节点联机添加到现有的NDB集群后,您希望将现有的NDB集群表数据重新分配给新数据节点。在这种情况下,您应该使用选项来调用声明
; 换句话说,如下所示:
partition_names INTO
(partition_definitions)HASHNDBALGORITHM=INPLACE
ALTER TABLE tableALGORITHM = INPLACE,REORGANIZE PARTITION;
在线表重组时不能执行其他DDL,也就是说,ALTER TABLE
... ALGORITHM=INPLACE, REORGANIZE PARTITION
执行语句时不能发出其他DDL语句。有关在线添加NDB群集数据节点的更多信息,请参见
第21.5.14节“在线添加NDB群集数据节点”。
ALTER TABLE ... ALGORITHM=INPLACE, REORGANIZE
PARTITION不适用于使用该MAX_ROWS
选项创建的表,因为它使用MAX_ROWS原始CREATE TABLE
语句中指定的常
量值来确定所需的分区数,因此不会创建新的分区。相反,您可以使用增加此表的最大行数; 在这种情况下,不需要(如果执行则会导致错误)。该值必须大于原始
值中指定的值
ALTER TABLE ...
ALGORITHM=INPLACE,
MAX_ROWS=rowsALTER TABLE ...
ALGORITHM=INPLACE, REORGANIZE PARTITIONrowsMAX_ROWSCREATE TABLE 声明这个工作。
MAX_ROWS在NDB 7.5.4和更高版本中不推荐
使用强制使用表分区的数量; 使用PARTITION_BALANCE
替代(见
设置NDB_TABLE选项)。
试图在REORGANIZE
PARTITION没有
显式分区表的选项的情况下
使用导致出现错误REORGANIZE PARTITION不带参数只能在使用HASH分区的自动分区表上使用。
partition_names INTO
(partition_definitions)
对于没有明确命名的分区,MySQL的自动提供的默认名称
p0,p1,
p2,等等。子分区也是如此。
有关ALTER TABLE ... REORGANIZE PARTITION
语句的更多详细信息和示例
,请参见
第22.3.1节“RANGE和LIST分区的管理”。
要将表分区或子分区与表交换,请使用ALTER
TABLE ... EXCHANGE PARTITION语句(即将分区或子分区中的所有现有行移至未分区表)以及将非分区表中的现有行移至表分区或子分区。
有关使用信息和示例,请参见 第22.3.3节“与表交换分区和子分区”。
有几个选项提供了分区维护和修复功能,类似于通过诸如CHECK TABLE和
REPAIR TABLE(这些分区表支持的语句;有关更多信息,请参见第13.7.2节“表维护语句”)为非分区表
执行的功能
。这些措施包括
ANALYZE PARTITION,CHECK
PARTITION,OPTIMIZE PARTITION,
REBUILD PARTITION,和REPAIR
PARTITION。每个选项都有一个
partition_names由一个或多个分区名称组成的子句,用逗号分隔。分区必须已经存在于表中才能被更改。您也可以使用ALL关键字代替partition_names在这种情况下,该语句将作用于所有表分区。有关更多信息和示例,请参见
第22.3.4节“维护分区”。
一些MySQL存储引擎,例如
InnoDB,不支持每分区优化。对于使用这种存储引擎的分区表,ALTER TABLE ... OPTIMIZE
PARTITION会导致重建和分析整个表,并发出相应的警告。(错误#11751825,错误#42822)
要解决此问题,使用的语句
ALTER TABLE ... REBUILD PARTITION和
ALTER TABLE ... ANALYZE PARTITION
替代。
在ANALYZE PARTITION,CHECK
PARTITION,OPTIMIZE PARTITION,和REPAIR PARTITION选项不允许未分区表。
REMOVE PARTITIONING使您能够删除表格的分区,而不会影响表格或其数据。此选项可以与其他ALTER TABLE选项(如用于添加,删除或重命名列或索引的选项)结合使用
。
使用该ENGINE选项
ALTER TABLE更改表使用的存储引擎,而不影响分区。
当ALTER TABLE ... EXCHANGE PARTITION或者
ALTER TABLE ... TRUNCATE PARTITION是针对使用分区表运行
MyISAM(或利用表级锁的另一个存储引擎),只有实际读取这些分区被锁定。(这不适用于使用存储引擎的分区表,例如使用行级锁定InnoDB。)请参见
第22.6.4节“分区和锁定”。
一条ALTER TABLE
语句可能包含一个PARTITION BY或
REMOVE PARTITIONING其他更改规范的附加条款,但必须在任何其他规范之后最后指定PARTITION
BYor REMOVE PARTITIONING子句。
的ADD PARTITION,DROP
PARTITION,COALESCE PARTITION,
REORGANIZE PARTITION,ANALYZE
PARTITION,CHECK PARTITION,和
REPAIR PARTITION选项不能与其他单一更改规格组合ALTER
TABLE,因为选择刚上市就单个分区的行为。有关更多信息,请参见
第13.1.8.1节“ALTER TABLE分区操作”。
只有以下任一选项的单个实例可以在给定的使用ALTER TABLE
声明:PARTITION BY,ADD
PARTITION,DROP PARTITION,
TRUNCATE PARTITION,EXCHANGE
PARTITION,REORGANIZE PARTITION,或
COALESCE PARTITION,ANALYZE
PARTITION,CHECK PARTITION,
OPTIMIZE PARTITION,REBUILD
PARTITION,REMOVE PARTITIONING。
例如,以下两条语句无效:
ALTER TABLE t1 ANALYZE PARTITION p1,ANALYZE PARTITION p2; ALTER TABLE t1 ANALYZE PARTITION p1,CHECK PARTITION p2;
在第一种情况下,您可以使用单个语句并行分析分区
p1和p2表,
t1并使用单个ANALYZE PARTITION选项列出要分析的两个分区,如下所示:
ALTER TABLE t1 ANALYZE PARTITION p1,p2;
在第二种情况下,不可能
同时在同一个表的不同分区上执行
ANALYZE和CHECK操作。相反,您必须发出两个单独的声明,如下所示:
ALTER TABLE t1 ANALYZE PARTITION p1; ALTER TABLE t1 CHECK PARTITION p2;
REBUILD子分区目前不支持操作。该REBUILD关键字明确禁止使用子分区,ALTER TABLE如果这样使用,则会导致
错误并显示错误。
CHECK PARTITION 并且 REPAIR
PARTITION当要检查或修复的分区包含任何重复键错误时操作失败。
有关这些语句的更多信息,请参见 第22.3.4节“维护分区”。
MySQL NDB Cluster 7.5支持使用ALTER TABLEMySQL服务器(ALGORITHM=DEFAULT|INPLACE|COPY)使用的标准语法进行在线表架构更改,并在其他地方进行了介绍。
NDB集群的一些较早发行版使用特定的语法来
NDB进行在线ALTER
TABLE操作。该语法已被删除。
在可变宽度的列表上添加和删除索引的操作NDB发生在线。在线操作不是复制; 也就是说,他们不要求重新创建索引。它们不锁定被NDB集群中的其他API节点访问所改变的表(但请参阅
本节后面的限制NDB集群联机操作)。对于NDB具有多个API节点的NDB群集中进行的表更改,此类操作不需要单用户模式
; 在线DDL操作期间交易可以不中断。
ALGORITHM=INPLACE可用于执行在线ADD COLUMN,ADD
INDEX(包括CREATE INDEX
报表),并DROP INDEX在操作
NDB表。在线重命名
NDB表也受支持。
目前,您无法在线添加基于磁盘的列到
NDB表格。这意味着,如果您希望将内存列添加到
NDB使用表级STORAGE DISK选项的表中
,则必须将新列声明为明确使用基于内存的存储。例如 - 假设你已经创建了表空间 - 假设
ts1你创建了表
t1,如下所示:
的MySQL>CREATE TABLE t1 (>c1 INT NOT NULL PRIMARY KEY,>c2 VARCHAR(30)>)>TABLESPACE ts1 STORAGE DISK>ENGINE NDB;查询OK,0行受影响(1.73秒) 记录:0重复:0警告:0
您可以在线添加一个新的内存列,如下所示:
MySQL的>ALTER TABLE t1>ADD COLUMN c3 INT COLUMN_FORMAT DYNAMIC STORAGE MEMORY,>ALGORITHM=INPLACE;查询OK,0行受影响(1.25秒) 记录:0重复:0警告:0
如果STORAGE MEMORY
省略该选项,则该语句失败:
的MySQL>ALTER TABLE t1>ADD COLUMN c4 INT COLUMN_FORMAT DYNAMIC,> ERROR 1846(0A000):不支持算法= INPLACE。原因:ALGORITHM=INPLACE;不支持在线添加列或添加/重新组织分区。尝试 算法= COPY。
如果省略该COLUMN_FORMAT DYNAMIC选项,将自动采用动态列格式,但会发出警告,如下所示:
MySQL的>ALTER ONLINE TABLE t1 ADD COLUMN c4 INT STORAGE MEMORY;查询OK,0行受影响,1个警告(1.17秒) 记录:0重复:0警告:0 MySQL的>SHOW WARNINGS\G*************************** 1. row ******************** ******* 级别:警告 代码:1478 消息:不支持具有存储磁盘的DYNAMIC列c4,列将显示 成为固定 MySQL的>SHOW CREATE TABLE t1\G*************************** 1. row ******************** ******* 表:t1 创建表:CREATE TABLE`t1`( `c1` int(11)NOT NULL, `c2` varchar(30)DEFAULT NULL, `c3` int(11)/ *!50606 STORAGE MEMORY * / / *!50606 COLUMN_FORMAT DYNAMIC * / DEFAULT NULL, `c4` int(11)/ *!50606 STORAGE MEMORY * / DEFAULT NULL, 主键(`c1`) )/ *!50606 TABLESPACE ts_1 STORAGE DISK * / ENGINE = ndbcluster DEFAULT CHARSET = latin1 一排(0.03秒)
在STORAGE和
COLUMN_FORMAT关键字仅在NDB集群支持; 在任何其他版本的MySQL中,尝试在a CREATE
TABLE或ALTER TABLE
语句中使用这些关键字中的任何一个都会导致错误。
也可以
在表上ALTER TABLE
... REORGANIZE PARTITION, ALGORITHM=INPLACE使用没有
选项的语句。这可用于在已添加到群集中的新数据节点之间重新分配NDB群集数据。这并
没有执行任何碎片整理,这需要一个或空语句。有关更多信息,请参见
第21.5.14节“在线添加NDB群集数据节点”。
partition_names INTO
(partition_definitions)NDBOPTIMIZE TABLEALTER TABLE
在线DROP COLUMN操作不受支持。
在线ALTER TABLE,
CREATE INDEX或
DROP INDEX添加列或添加或删除索引的语句受以下限制:
一个给定的网络ALTER TABLE
可以使用只有一个ADD COLUMN,
ADD INDEX或DROP
INDEX。一个或多个列可以在一个语句中在线添加; 只有一个索引可能会在单个语句中创建或删除在线。
正在修改的表是不是就比上一个网上的另外一个API节点锁定
,或
操作(或
或
语句)运行。但是,在执行在线操作时,该表锁定了源自同一 API节点的任何其他操作。
ALTER TABLE ADD
COLUMNADD INDEXDROP INDEXCREATE INDEXDROP INDEX
要更改的表必须具有明确的主键; NDB存储引擎创建的隐藏主键
不足以实现此目的。
表格使用的存储引擎不能在线更改。
与NDB群集磁盘数据表一起使用时,无法在线更改列的存储类型(DISK
或MEMORY)。这意味着,当您添加或删除一个索引以便在线执行操作并且希望更改一列或多列的存储类型时,您必须ALGORITHM=COPY在添加或删除索引的语句中使用。
要在线添加的列不能使用
BLOB或
TEXT类型,并且必须符合以下条件:
这些列必须是动态的; 也就是说,它必须可以使用创建它们COLUMN_FORMAT DYNAMIC。如果您省略该COLUMN_FORMAT DYNAMIC
选项,则会自动采用动态列格式。
这些列必须允许NULL值,而不是任何明确的默认值
NULL。在线添加的列会自动创建DEFAULT NULL,如下所示:
MySQL的>CREATE TABLE t2 (>c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY>) ENGINE=NDB;查询OK,0行受影响(1.44秒) 的MySQL>ALTER TABLE t2>ADD COLUMN c2 INT,>ADD COLUMN c3 INT,>ALGORITHM=INPLACE;查询OK,0行受影响,2个警告(0.93秒) MySQL的>SHOW CREATE TABLE t1\G*************************** 1. row ******************** ******* 表:t1 创建表:CREATE TABLE`t2`( `c1` int(11)NOT NULL AUTO_INCREMENT, `c2` int(11)DEFAULT NULL, `c3` int(11)DEFAULT NULL, 主键(`c1`) )ENGINE = ndbcluster DEFAULT CHARSET = latin1 一排(0.00秒)
必须在任何现有列之后添加列。如果您尝试在任何现有列之前或使用FIRST关键字之前联机添加列,则语句会失败并显示错误。
现有表格列不能在线重新排序。
对于表格的联机ALTER TABLE操作NDB,固定格式列在联机添加时或在线创建或删除索引时会转换为动态格式,如下所示(为了清楚起见,重复刚刚显示的CREATE TABLE和ALTER
TABLE语句):
MySQL的>CREATE TABLE t2 (>c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY>) ENGINE=NDB;查询OK,0行受影响(1.44秒) 的MySQL>ALTER TABLE t2>ADD COLUMN c2 INT,>ADD COLUMN c3 INT,>ALGORITHM=INPLACE;查询OK,0行受影响,2个警告(0.93秒) MySQL的>SHOW WARNINGS;*************************** 1. row ******************** ******* 级别:警告 代码:1478 消息:将FIXED字段'c2'转换为DYNAMIC以启用在线ADD COLUMN *************************** 2. row ******************** ******* 级别:警告 代码:1478 消息:将FIXED字段'c3'转换为DYNAMIC以启用在线ADD COLUMN 设置2行(0.00秒)
只有在线添加的列必须是动态的。现有的列不一定是; 这包括表的主键,也可以FIXED如下所示:
MySQL的>CREATE TABLE t3 (>c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY COLUMN_FORMAT FIXED>) ENGINE=NDB;查询OK,0行受影响(2.10秒) MySQL的>ALTER TABLE t3 ADD COLUMN c2 INT, ALGORITHM=INPLACE;查询OK,0行受影响,1个警告(0.78秒) 记录:0重复:0警告:0 MySQL的>SHOW WARNINGS;*************************** 1. row ******************** ******* 级别:警告 代码:1478 消息:将FIXED字段'c2'转换为DYNAMIC以启用在线ADD COLUMN 一排(0.00秒)
通过重命名操作FIXED,DYNAMIC列
不会转换为
列格式。有关更多信息COLUMN_FORMAT,请参见
第13.1.18节“CREATE TABLE语法”。
的KEY,CONSTRAINT和
IGNORE关键字都以支持
ALTER TABLEusing语句
ALGORITHM=INPLACE。
从NDB集群7.5.7和7.6.3开始,不允许MAX_ROWS使用在线ALTER
TABLE语句设置
为0 。您必须使用复制
ALTER TABLE才能执行此操作。(Bug#21960004)
ALTER TABLE允许生成的列操作是ADD,
MODIFY,和CHANGE。
生成的列可以添加。
生成列的数据类型和表达式可以修改。
生成的列可以重命名或删除,如果没有其他列引用它们。
虚拟生成的列不能更改为存储生成的列,反之亦然。要解决此问题,请删除该列,然后将其添加到新定义中。
未生成的列可以更改为已存储的列,但不能生成虚拟列。
存储但不是虚拟生成的列可以更改为未生成的列。存储的生成值将成为非生成列的值。
ADD COLUMN不是对存储列的就地操作(不使用临时表完成),因为表达式必须由服务器评估。对于存储的列,索引更改已完成,并且表达式更改没有完成。对列注释的更改已完成。
对于未分区的表,ADD COLUMN
并且DROP COLUMN是虚拟列的就地操作。但是,添加或删除虚拟列无法与其他ALTER TABLE操作结合使用。
对于分区表,ADD COLUMN并
DROP COLUMN没有对虚拟列就地操作。
InnoDB支持虚拟生成列上的二级索引。在虚拟生成的列上添加或删除辅助索引是就地操作。有关更多信息,请参见
第13.1.18.9节“二级索引和生成的列”。
将VIRTUAL生成的列添加到表中或进行修改时,无法确保生成的列表达式计算的数据不会超出列的范围。这可能会导致返回的数据不一致,并导致意外失败的语句。为了控制是否对这些列,ALTER TABLE支持
WITHOUT VALIDATION和WITH
VALIDATION子句进行验证:
使用WITHOUT VALIDATION(如果既没有指定任何默认子句,也执行默认操作),执行就地操作(如果可能),不检查数据完整性,并且语句更快完成。但是,如果值超出范围,稍后从表中读取可能会报告列的警告或错误。
用WITH VALIDATION,ALTER
TABLE复制表格。如果发生超出范围或任何其他错误,则说明失败。由于执行了表副本,因此该语句需要更长的时间。
WITHOUT VALIDATION并且WITH
VALIDATION只有被允许ADD
COLUMN,CHANGE COLUMN和
MODIFY COLUMN操作。否则,
ER_WRONG_USAGE会发生错误。
从MySQL 5.7.10开始,如果表达式求值会导致截断或向函数提供不正确的输入,则该
ALTER TABLE语句会因错误而终止,并且DDL操作将被拒绝。
ALTER TABLE更改列的默认值
的语句也
col_name可能会更改引用该列的生成列表达式的值
。由于这个原因,从MySQL 5.7.13开始,
如果任何生成的列表达式使用,那么现在更改列定义的操作会导致表重建
。
DEFAULT(col_name)ALTER TABLEDEFAULT()
从t1创建的表格开始,如下所示:
CREATE TABLE t1(INTEGER,b CHAR(10));
将表格重命名t1为
t2:
ALTER TABLE t1 RENAME t2;
若要更改列a从
INTEGER给TINYINT NOT
NULL(名字一样),并更改列
b从CHAR(10)到
CHAR(20)以及来自重命名
b到c:
ALTER TABLE t2 MODIFY a TINYINT NOT NULL,CHANGE bc CHAR(20);
要添加TIMESTAMP名为的新列d:
ALTER TABLE t2 ADD d TIMESTAMP;
在列上添加索引d并
UNIQUE在列上添加索引a:
ALTER TABLE t2 ADD INDEX(d),ADD UNIQUE(a);
删除列c:
ALTER TABLE t2 DROP COLUMN c;
要添加AUTO_INCREMENT名为的新整数列c:
ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, 添加主键(c);
我们索引c(作为PRIMARY
KEY),因为AUTO_INCREMENT列必须被索引,我们宣布c为
NOT NULL是因为主键列不能NULL。
对于NDB表格,还可以更改用于表格或列的存储类型。例如,考虑NDB创建一个如下所示的表格:
MySQL的> CREATE TABLE t1 (c1 INT) TABLESPACE ts_1 ENGINE NDB;
查询OK,0行受影响(1.27秒)
要将此表转换为基于磁盘的存储,可以使用以下ALTER TABLE语句:
MySQL的>ALTER TABLE t1 TABLESPACE ts_1 STORAGE DISK;查询OK,0行受影响(2.99秒) 记录:0重复:0警告:0 MySQL的>SHOW CREATE TABLE t1\G*************************** 1. row ******************** ******* 表:t1 创建表:CREATE TABLE`t1`( `c1` int(11)DEFAULT NULL )/ *!50100 TABLESPACE ts_1 STORAGE DISK * / ENGINE = ndbcluster DEFAULT CHARSET = latin1 一排(0.01秒)
表格最初创建时不需要引用表空间; 但是,表空间必须由以下内容引用ALTER TABLE:
MySQL的>CREATE TABLE t2 (c1 INT) ts_1 ENGINE NDB;查询OK,0行受影响(1.00秒) mysql> ERROR 1005(HY000):无法创建表'c。#sql-1750_3'(errno:140) mysql>ALTER TABLE t2 STORAGE DISK;ALTER TABLE t2 TABLESPACE ts_1 STORAGE DISK;查询OK,0行受影响(3.42秒) 记录:0重复:0警告:0 MySQL的>SHOW CREATE TABLE t2\G*************************** 1. row ******************** ******* 表:t1 创建表:CREATE TABLE`t2`( `c1` int(11)DEFAULT NULL )/ *!50100 TABLESPACE ts_1 STORAGE DISK * / ENGINE = ndbcluster DEFAULT CHARSET = latin1 一排(0.01秒)
要更改单个列的存储类型,可以使用
ALTER TABLE ... MODIFY [COLUMN]。例如,假设您使用以下CREATE TABLE
语句创建具有两列的NDB群集磁盘数据表:
mysql>CREATE TABLE t3 (c1 INT, c2 INT)- >TABLESPACE ts_1 STORAGE DISK ENGINE NDB;查询OK,0行受影响(1.34秒)
要将列c2从基于磁盘转换为内存中存储,请在ALTER TABLE语句使用的列定义中包含STORAGE MEMORY子句,如下所示:
MySQL的> ALTER TABLE t3 MODIFY c2 INT STORAGE MEMORY;
查询OK,0行受影响(3.14秒)
记录:0重复:0警告:0
您可以使用STORAGE DISK类似的方式将内存列写入基于磁盘的列中。
列c1使用基于磁盘的存储,因为这是表的默认值(由STORAGE DISK语句中的表级子句
确定
CREATE TABLE)。但是,列c2使用内存中的存储空间,可以在SHOW的输出中看到CREATE
TABLE:
MySQL的> SHOW CREATE TABLE t3\G
*************************** 1. row ******************** *******
表:t3
创建表:CREATE TABLE`t3`(
`c1` int(11)DEFAULT NULL,
`c2` int(11)/ *!50120 STORAGE MEMORY * / DEFAULT NULL
)/ *!50100 TABLESPACE ts_1 STORAGE DISK * / ENGINE = ndbcluster DEFAULT CHARSET = latin1
一排(0.02秒)
添加AUTO_INCREMENT列时,列值将自动填入序列号。对于
MyISAM表格,您可以通过在执行之前
或通过使用
表格选项来设置第一个序列号。
SET
INSERT_ID=valueALTER TABLEAUTO_INCREMENT=value
使用MyISAM表格,如果您不更改
AUTO_INCREMENT列,则序号不受影响。如果您放下一AUTO_INCREMENT
列然后再添加一AUTO_INCREMENT
列,则数字将从1开始重新排序。
使用复制时,向AUTO_INCREMENT表中添加
列可能不会产生从属和主控上的行的相同排序。这是因为行编号的顺序取决于表中使用的特定存储引擎以及行插入的顺序。如果在主站和从站上具有相同的顺序很重要,则必须在分配AUTO_INCREMENT数字之前对行进行排序
。假设您想向AUTO_INCREMENT表中添加一列
t1,以下语句将生成一个t2与表格相同t1
但具有一AUTO_INCREMENT列的新表格:
CREATE TABLE t2(id INT AUTO_INCREMENT PRIMARY KEY) SELECT * FROM t1 ORDER BY col1,col2;
这假定该表t1具有列
col1和col2。
这组语句也将产生一个新的表
t2相同t1,加上一个的AUTO_INCREMENT列:
CREATE TABLE t2 LIKE t1; ALTER TABLE t2 ADD id INT AUTO_INCREMENT PRIMARY KEY; INSERT INTO t2 SELECT * FROM t1 ORDER BY col1,col2;
为保证主站和从站的顺序相同
,必须在子句中引用所有列。
t1ORDER BY
不管用于创建和填充具有该AUTO_INCREMENT列的副本的方法,最后一步是删除原始表,然后重新命名副本:
DROP TABLE t1; ALTER TABLE t2 RENAME t1;
ALTER TABLESPACEtablespace_name{ADD | DROP} DATAFILE'file_name' [INITIAL_SIZE [=]size] [等待] ENGINE [=]engine_name
这个语句可以用来添加一个新的数据文件,或者从表空间中删除一个数据文件。
该ADD DATAFILE变体使您能够使用INITIAL_SIZE子句指定初始大小,其中size以字节为单位进行测量; 默认值是134217728(128 MB)。您可以选择遵循
size一个数量级的单字母缩写,类似于中使用的缩写
my.cnf。通常,这是字母
M(兆字节)或G
(千兆字节)之一。
所有NDB群集磁盘数据对象共享相同的名称空间。这意味着每个磁盘数据对象必须是唯一命名的(而不仅仅是给定类型的每个磁盘数据对象)。例如,您不能拥有同名的表空间和数据文件,或者具有相同名称的撤消日志文件和表空间。
在32位系统上,支持的最大值为
INITIAL_SIZE4294967296(4 GB)。(错误#29186)
INITIAL_SIZE明确地说,是圆形的
CREATE TABLESPACE。
一旦数据文件被创建,其大小不能改变; 但是,您可以使用附加ALTER TABLESPACE ... ADD DATAFILE
语句将更多数据文件添加到表空间。
使用DROP DATAFILE与
ALTER TABLESPACE下降的数据文件“ file_name从表”。您不能从任何表正在使用的表空间中删除数据文件; 换句话说,数据文件必须是空的(没有扩展使用)。请参见第21.5.13.1节“NDB群集磁盘数据对象”。另外,任何要删除的数据文件必须先前已经添加到带有CREATE
TABLESPACE或的表空间中ALTER
TABLESPACE。
二者ALTER TABLESPACE ... ADD DATAFILE并
ALTER TABLESPACE ... DROP DATAFILE需要
ENGINE其指定由所述表中使用的存储引擎子句。目前,唯一可接受的值engine_name是
NDBand
NDBCLUSTER。
WAIT被解析,但被忽略,所以在MySQL 5.7中没有效果。它旨在用于未来的扩展。
何时ALTER TABLESPACE ... ADD DATAFILE与ENGINE = NDB每个群集数据节点上创建一个数据文件。您可以验证数据文件是否已创建,并通过查询INFORMATION_SCHEMA.FILES表获取有关它们的信息
。例如,以下查询显示属于名为的表空间的所有数据文件newts:
mysql>SELECT LOGFILE_GROUP_NAME, FILE_NAME, EXTRA- >FROM INFORMATION_SCHEMA.FILES- >WHERE TABLESPACE_NAME = 'newts' AND FILE_TYPE = 'DATAFILE';+ -------------------- + -------------- + ------------- --- + | LOGFILE_GROUP_NAME | FILE_NAME | EXTRA | + -------------------- + -------------- + ------------- --- + | lg_3 | newdata.dat | CLUSTER_NODE = 3 | | lg_3 | newdata.dat | CLUSTER_NODE = 4 | | lg_3 | newdata2.dat | CLUSTER_NODE = 3 | | lg_3 | newdata2.dat | CLUSTER_NODE = 4 | + -------------------- + -------------- + ------------- --- + 2排(0.03秒)
请参见第24.8节“INFORMATION_SCHEMA文件表”。
ALTER TABLESPACE仅适用于NDB群集的磁盘数据存储。请参见
第21.5.13节“NDB群集磁盘数据表”。
改变
[ALGORITHM = {未定义| MERGE | 不是Temptable}]
[DEFINER = { user| 当前用户 }]
[SQL SECURITY {DEFINER | INVOKER}]
VIEW view_name[(column_list)]
如 select_statement
[WITH [CASCADED | LOCAL]检查选项]
这个语句改变了必须存在的视图的定义。语法是类似于对CREATE
VIEW见第13.1.21,“CREATE VIEW语法”)。该声明要求CREATE VIEW和
DROP特权的观点,以及一些特权每一列中提到
SELECT的语句。
ALTER VIEW只允许定义者或有SUPER
特权的用户。
创建{DATABASE | SCHEMA} [如果不存在] db_name
[ create_specification] ...
create_specification:
[DEFAULT] CHARACTER SET [=] charset_name
| [DEFAULT] COLLATE [=]collation_name
CREATE DATABASE用给定的名字创建一个数据库。要使用此语句,您需要CREATE数据库的
特权。
CREATE
SCHEMA是一个同义词CREATE
DATABASE。
如果数据库存在并且您没有指定,则会发生错误
IF NOT EXISTS。
CREATE DATABASE在具有活动LOCK
TABLES语句的会话中不允许。
create_specification选项指定数据库特征。数据库特征存储在db.opt数据库目录中的文件中。该CHARACTER SET子句指定了默认的数据库字符集。该COLLATE子句指定默认的数据库排序规则。
第10章,字符集,排序规则,Unicode讨论了字符集和排序规则名称。
MySQL中的数据库实现为包含与数据库中的表对应的文件的目录。由于数据库中最初创建时没有表,因此
CREATE DATABASE语句仅在MySQL数据目录和db.opt文件下创建一个目录
。允许数据库名称的规则在第9.2节“模式对象名称”中给出。如果数据库名称包含特殊字符,则数据库目录的名称将包含这些字符的编码版本,如第9.2.3节“将标识符映射到文件名称”中所述。
如果您在数据目录下手动创建目录(例如,使用mkdir),服务器将其视为数据库目录,并显示在输出中
SHOW DATABASES。
您也可以使用mysqladmin程序来创建数据库。请参见第4.5.2节“ mysqladmin - 管理MySQL服务器的客户端”。
创建
[DEFINER = { user| 当前用户 }]
事件
[如果不存在]
event_name
按照时间表 schedule
[完成[不]保存]
[启用| DISABLE | 禁止在奴隶]
[评论' string']
DO event_body;
schedule:
AT timestamp[+ INTERVAL interval] ...
| 每个interval
[开始timestamp[+ INTERVAL interval] ...]
[结束timestamp[+ INTERVAL interval] ...]
interval:
quantity{YEAR | QUARTER | 月| DAY | HOUR | MINUTE |
WEEK | 第二| | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
此声明创建并安排新的事件。除非事件计划程序已启用,否则该事件将不会运行。有关检查事件调度程序状态并在必要时启用它的信息,请参见第23.4.2节“事件调度程序配置”。
CREATE EVENT需要
EVENT特权才能创建事件的模式。它也可能需要
SUPER权限,具体取决于
DEFINER值,如本节后面所述。
有效CREATE
EVENT声明的最低要求如下:
关键字CREATE EVENT加上一个事件名称,它唯一标识数据库模式中的事件。
一个ON SCHEDULE子句,用于确定事件执行的时间和频率。
一个DO子句,其中包含要由事件执行的SQL语句。
这是一个最小CREATE
EVENT声明的例子:
创建事件myevent
在CURRENT_TIMESTAMP + INTERVAL 1小时安排时间表
做
UPDATE myschema.mytable SET mycol = mycol + 1;
前面的语句创建一个名为的事件
myevent。此事件在其创建后执行一次 - 通过运行将myschema.mytable
表格mycol列的值递增1的SQL语句。
在event_name必须与64个字符的最大长度一个有效的MySQL标识符。事件名称是不区分大小写,所以你不能有两个名为事件
myevent,并MyEvent在同一个模式。通常,管理事件名称的规则与存储例程的名称相同。请参见
第9.2节“模式对象名称”。
事件与架构相关联。如果没有模式被指定为部分event_name,则假定默认(当前)模式。要在特定模式中创建事件,请使用
语法使用模式限定事件名称
。
schema_name.event_name
该DEFINER子句指定在事件执行时检查访问特权时要使用的MySQL帐户。如果user给出值,它应该指定为MySQL账户
,
或
。缺省
值是执行语句的用户
。这与
明确指定相同。
'user_name'@'host_name'CURRENT_USERCURRENT_USER()DEFINERCREATE EVENTDEFINER = CURRENT_USER
如果您指定了该DEFINER子句,则这些规则将确定有效的DEFINER用户值:
如果您没有SUPER
权限,唯一允许的user
值是您自己的帐户,无论是按字面还是使用指定CURRENT_USER。您无法将定义者设置为某个其他帐户。
如果您有SUPER
权限,则可以指定任何语法上有效的帐户名称。如果该帐户不存在,则会生成警告。
虽然可以使用不存在的DEFINER帐户创建事件,但
如果帐户不存在,则会在事件执行时发生错误。
有关事件安全性的更多信息,请参见 第23.6节“存储程序和视图的访问控制”。
在事件中,该CURRENT_USER()
函数返回用于在事件执行时检查权限的帐户,该DEFINER用户是该用户。有关事件内用户审计的信息,请参见
第6.3.12节“基于SQL的MySQL账户活动审计”。
IF NOT EXISTS具有相同的含义为
CREATE EVENT为
CREATE TABLE:如果命名的事件
event_name已经在相同的模式存在,不采取任何行动,而不会出现错误。(但是,在这种情况下会产生警告。)
该ON SCHEDULE条款确定event_body
事件定义的时间,频率和时间重复。本条款采取两种形式之一:
AT 用于一次性事件。它指定事件只在指定的日期和时间执行一次
timestamptimestamp,必须包含日期和时间,或者必须是解析为日期时间值的表达式。您可以为此使用DATETIME或者
TIMESTAMP类型的值
。如果日期过去,则会发生警告,如下所示:
MySQL的>SELECT NOW();+ --------------------- + | NOW()| + --------------------- + | 2006-02-10 23:59:01 | + --------------------- + 一排(0.04秒) mysql>CREATE EVENT e_totals- >ON SCHEDULE AT '2006-02-10 23:59:00'- >DO INSERT INTO test.totals VALUES (NOW());查询确定,0行受影响,1个警告(0.00秒) MySQL的>SHOW WARNINGS\G*************************** 1. row ******************** ******* 级别:注意 代码:1588 消息:事件执行时间在过去,ON COMPLETION NOT PRESERVE已设置。事件之后立即下降 创建。
CREATE EVENT 本身无效的语句 - 无论出于何种原因 - 都会因错误而失败。
您可以使用CURRENT_TIMESTAMP
指定当前的日期和时间。在这种情况下,事件一旦创建就会发挥作用。
要创建相对于当前日期和时间在将来某个时间点发生的事件 - 例如“ 从现在起三周后 ”所表达的事件 - 您可以使用可选的子句。该
部分由两部分组成,即数量和时间单位,并遵循相同的语法规则来管理函数中使用的时间间隔
(参见
第12.7节“日期和时间函数”)。单位关键字也是相同的,除了定义事件时不能使用任何涉及微秒的单位,对于某些间隔类型,可以使用复杂的时间单位,例如
“+
INTERVAL intervalintervalDATE_ADD()两分十秒 “可以表示为
+ INTERVAL '2:10' MINUTE_SECOND。
您也可以合并间隔。例如,AT
CURRENT_TIMESTAMP + INTERVAL 3 WEEK + INTERVAL 2 DAY
相当于“ 从现在开始的三周和两天 ”。这种条款的每一部分都必须以
+ INTERVAL。
要定期重复操作,请使用
EVERY子句。的EVERY
关键字后面是一个interval
如在以前的讨论中所描述
AT的关键字。(+ INTERVAL
是不与所用
EVERY。)例如,EVERY 6
WEEK是指“ 每六周 ”。
尽管+ INTERVAL子句中不允许使用EVERY子句,但可以使用与a中允许的相同的复杂时间单位+
INTERVAL。
一个EVERY子句可能包含一个可选的
STARTS子句。STARTS之后是一个timestamp值,指示动作何时应该开始重复,也可以用于指定“ 从现在开始 ”的时间量。例如,
意思是“ 每三个月,从现在起一周开始 ”。同样,你可以表达“ 每两个星期,开始6小时15分钟从现在开始 ”的。不指定
与使用相同+ INTERVAL
intervalEVERY 3 MONTH STARTS CURRENT_TIMESTAMP + INTERVAL 1
WEEKEVERY 2 WEEK STARTS CURRENT_TIMESTAMP
+ INTERVAL '6:15' HOUR_MINUTESTARTSSTARTS
CURRENT_TIMESTAMP也就是说,事件指定的动作在创建事件后立即开始重复。
一个EVERY子句可能包含一个可选的
ENDS子句。该ENDS
关键字后跟timestamp
告诉MySQL时,该事件应停止重复值。您也可以使用带有
; 例如,相当于
“ 每十二小时,从现在起三十分钟开始,从现在开始四周结束 ”。不使用
意味着事件将无限期地继续执行。
+ INTERVAL
intervalENDSEVERY 12 HOUR
STARTS CURRENT_TIMESTAMP + INTERVAL 30 MINUTE ENDS
CURRENT_TIMESTAMP + INTERVAL 4 WEEKENDS
ENDS支持与复杂时间单位相同的语法STARTS。
你可以在一个子句中使用STARTS,ENDS既
可以,
也可以不使用EVERY。
如果重复事件不在其调度间隔内终止,则结果可能是同时执行的事件的多个实例。如果这是不可取的,你应该建立一个机制来防止同时发生的事件。例如,您可以使用该
GET_LOCK()函数或行或表锁定。
该ON SCHEDULE子句可以使用涉及内置MySQL函数和用户变量的表达式来获取它所包含的任何timestamp或
interval值。您不得在这些表达式中使用存储的函数或用户定义的函数,也不得使用任何表引用; 但是,您可以使用SELECT FROM DUAL。对于两者CREATE EVENT和
ALTER EVENT陈述都是如此
。在这种情况下,对存储函数,用户定义的函数和表的引用是不允许的,并且会失败并返回错误(请参阅错误#22830)。
在时代ON SCHEDULE条款使用当前会话解释
time_zone值。这成为事件时区; 即用于事件调度的时区,并在执行时在事件内生效。这些时间将转换为UTC并与mysql.event表中的事件时区一起存储。这可以使事件执行按照定义继续进行,而不管后续对服务器时区或夏令时效果所做的任何更改。有关事件时间表示的其他信息,请参见第23.4.4节“事件元数据”。另请参见
第13.7.5.18节“SHOW EVENTS语法”和第24.7节“INFORMATION_SCHEMA事件表”。
通常,一旦事件已经过期,它会立即被删除。您可以通过指定来覆盖此行为ON
COMPLETION PRESERVE。ON COMPLETION NOT
PRESERVE仅仅使用默认的非持久行为是显式的。
您可以创建一个事件,但使用DISABLE关键字阻止它处于活动状态
。或者,您可以使用
ENABLE来明确默认状态,该状态处于活动状态。这是最有用的
ALTER EVENT(参见
第13.1.2节“ALTER EVENT语法”)。
第三个值也可以代替ENABLE或出现
DISABLE;
DISABLE ON SLAVE被设置为复制从站上事件的状态,以指示事件在主站上创建并复制到从站,但不在从站上执行。请参见
第16.4.1.16节“调用的功能的复制”。
您可以使用COMMENT条款提供对事件的评论
。
comment可能是您希望用于描述事件的最多64个字符的任何字符串。注释文本是一个字符串文字,必须用引号括起来。
该DO子句指定由该事件携带的动作,并由一个SQL语句组成。几乎任何可以在存储例程中使用的有效MySQL语句也可以用作预定事件的操作语句。(请参见
第C.1节“对存储程序的限制”。)例如,以下事件每小时e_hourly删除sessions表中的所有行,其中此表是site_activity模式的一部分:
创建事件e_hourly
按照时间表
每个1小时
评论'每小时清除会话表'。
做
DELETE FROM site_activity.sessions;
sql_mode当创建或更改事件时,
MySQL存储系统变量设置,并始终使用此设置执行该事件,
而不管当事件开始执行时的当前服务器SQL模式。
一个CREATE EVENT包含一个声明ALTER EVENT它在声明中DO条款似乎是成功的; 但是,当服务器尝试执行结果的预定事件时,执行失败并出现错误。
在事件中使用SELECT或
SHOW仅返回结果集的
语句不起作用; 这些输出不会发送到MySQL Monitor,也不会存储到任何地方。但是,您可以使用SELECT ...
INTO和
INSERT INTO ...
SELECT存储结果等语句
。(有关后者的一个实例,请参阅本节中的下一个示例。)
事件所属的模式是DO子句中表引用的默认模式。任何对其他模式中表的引用都必须使用正确的模式名称进行限定。
与存储例程一样,可以使用和关键字在DO子句中
使用复合语句语法,如下所示:
BEGINEND
分隔符|
创建事件e_daily
按照时间表
每一天
评论'保存会话总数然后每天清理表格'
做
开始
INSERT INTO site_activity.totals(时间,总计)
SELECT CURRENT_TIMESTAMP,COUNT(*)
FROM site_activity.sessions;
DELETE FROM site_activity.sessions;
END |
定界符
本示例使用该delimiter命令更改语句分隔符。请参见
第23.1节“定义存储的程序”。
更复杂的复合语句(例如存储例程中使用的复合语句)在事件中是可能的。本例使用局部变量,错误处理程序和流程控制结构:
分隔符|
创建活动e
按照时间表
每5秒
做
开始
DECLARE v INTEGER;
为SQLEXCEPTION开始END DECALARE CONTINUE HANDLER;
SET v = 0;
当v <5时
INSERT INTO t1 VALUES(0);
UPDATE t2 SET s1 = s1 + 1;
SET v = v + 1;
END WHILE;
END |
定界符
没有办法将参数直接传递给事件或从事件传递; 但是,可以使用事件中的参数调用存储的例程:
创建事件e_call_myproc
按照时间表
AT CURRENT_TIMESTAMP + INTERVAL 1天
DO CALL myproc(5,27);
如果事件的定义者有SUPER
权限,则该事件可以读写全局变量。由于授予此特权有可能造成滥用,因此必须格外小心。
通常,在存储例程中有效的任何语句都可以用于由事件执行的操作语句。有关存储例程中允许的语句的更多信息,请参见第23.2.1节“存储例程语法”。您可以创建一个事件作为存储例程的一部分,但事件不能由另一个事件创建。
该CREATE FUNCTION语句用于创建存储的函数和用户定义的函数(UDF):
有关创建存储函数的信息,请参见 第13.1.16节“CREATE PROCEDURE和CREATE FUNCTION语法”。
有关创建用户定义函数的信息,请参见 第13.7.3.1节“用户定义函数的CREATE FUNCTION语法”。
创建[独特|全部|空间]索引index_name[index_type] ONtbl_name(index_col_name,...) [index_option] [algorithm_option|lock_option] ...index_col_name:col_name[(length)] [ASC | DESC]index_option: KEY_BLOCK_SIZE [=]value|index_type| 与PARSERparser_name| 评论'string'index_type: 使用{BTREE | HASH}algorithm_option: 算法[=] {默认|输入|复制}lock_option: LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}
CREATE INDEX被映射到一个
ALTER TABLE语句来创建索引。请参见第13.1.8节“ALTER TABLE语法”。
CREATE INDEX不能用于创建一个PRIMARY KEY; ALTER TABLE改为使用
。有关索引的更多信息,请参见第8.3.1节“MySQL如何使用索引”。
通常,在创建表本身时,您可以在表上创建所有索引CREATE
TABLE。请参见第13.1.18节“CREATE TABLE语法”。该指南对InnoDB表格尤为重要
,其中主键确定数据文件中行的物理布局。
CREATE INDEX使您能够将索引添加到现有表中。
表单的列列表(col1, col2, ...)
创建一个多列索引。索引键值通过连接给定列的值形成。
对于字符串列,可以创建仅使用列值的前导部分
的索引,并使用
语法来指定索引前缀长度:
col_name(length)
前缀限制以字节为单位,而在前缀长度CREATE TABLE,
ALTER TABLE和
CREATE INDEX语句被解释为非二进制串类型的字符数(CHAR,
VARCHAR,
TEXT二进制串类型()和字节数BINARY,
VARBINARY,
BLOB)。为使用多字节字符集的非二进制字符串列指定前缀长度时,请考虑这一点。
对于空间列,不能给出前缀值,如本节后面所述。
此处显示的语句使用列的前10个字符创建索引name(假设它
name具有非二进制字符串类型):
CREATE INDEX part_of_name ON customer(name(10));
如果列中的名称通常在前10个字符中不相同,则此索引不应比从整name列创建的索引慢得多。另外,对索引使用列前缀可以使索引文件更小,这可以节省大量的磁盘空间并且还可以加速
INSERT操作。
前缀支持和前缀长度(如果支持)取决于存储引擎。例如,InnoDB如果innodb_large_prefix
启用该选项,则前缀长度可以高达767个字节,对于表或3072个字节。对于MyISAM表格,前缀限制是1000字节。该
NDB存储引擎不支持前缀(见
第21.1.6.6,“在NDB簇不支持或缺失的功能”)。
NDB集群以前CREATE
INDEX使用不再支持的替代语法支持在线操作。NDB集群现在支持ALGORITHM=INPLACE使用与标准MySQL服务器相同语法的在线操作。有关更多信息,请参见
第13.1.8.2节“NDB集群中的ALTER TABLE联机操作”。
一个UNIQUE索引创建的约束,使得该指数的所有值必须是不同的。如果尝试使用与现有行匹配的键值添加新行,则会发生错误。对于所有引擎,UNIQUE索引允许NULL包含多个列的值NULL。如果您为UNIQUE索引中的列指定前缀值,则列值在前缀中必须是唯一的。
如果一个UNIQUE索引只包含一个具有整数类型的列,那么您也可以_rowid在SELECT
语句中引用该列
。
从MySQL 5.7.17开始,如果指定的索引前缀超过最大列数据类型大小,则按CREATE
INDEX如下所示处理索引:
对于非唯一索引,如果发生错误(如果启用严格SQL模式),或者索引长度降低到位于最大列数据类型大小范围内并产生警告(如果严格模式未启用)。
对于唯一索引,无论SQL模式如何都会发生错误,因为减少索引长度可能会导致插入不符合指定唯一性要求的非唯一条目。
FULLTEXT索引仅支持
InnoDB和
MyISAM表格,并且可以只包括
CHAR,
VARCHAR和
TEXT列。索引总是发生在整个列上; 列前缀索引不受支持,并且如果指定,则任何前缀长度都将被忽略。有关操作的详细信息,请参见
第12.9节“全文搜索功能”。
的MyISAM,
InnoDB,
NDB,和
ARCHIVE存储引擎支持空间列,如(POINT和
GEOMETRY。(第11.5节,“空间数据类型”中描述的空间数据类型。)然而,对于空间列索引支持发动机的不同而不同。空间和非空间索引是根据可用遵循以下规则。
空间索引(使用创建SPATIAL INDEX)具有以下特征:
非空间指标的特性(与创建
INDEX,UNIQUE或
PRIMARY KEY):
允许用于任何支持空间列的存储引擎ARCHIVE。
NULL除非索引是主键,否则
可以是列。
对于SPATIAL
除POINT列以外的非索引中的每个空间列,必须指定列前缀长度。(这与索引BLOB
列的要求相同。)前缀长度以字节为单位给出。
非SPATIAL索引的索引类型取决于存储引擎。目前使用B树。
innodb_stats_persistent
启用
该
设置后,在该表上创建索引后运行该表的ANALYZE
TABLE语句
InnoDB。
InnoDB支持虚拟列上的二级索引。有关更多信息,请参见
第13.1.18.9节“二级索引和生成的列”。
的index_col_name规格可以与结束ASC或DESC。这些关键字可用于将来的扩展,用于指定升序或降序索引值存储。目前,他们被解析但被忽略; 索引值始终以升序存储。
在索引列表之后,可以给出索引选项。的
index_option值可以是任何以下的:
KEY_BLOCK_SIZE [=]
value
对于MyISAM表,
KEY_BLOCK_SIZE可选地指定用于索引关键字块的字节大小。该值被视为提示; 如有必要,可以使用不同的尺寸。KEY_BLOCK_SIZE为单个索引定义指定的值将覆盖表级别的
KEY_BLOCK_SIZE值。
KEY_BLOCK_SIZE在InnoDB表的索引级别不受支持。请参见第13.1.18节“CREATE TABLE语法”。
index_type
某些存储引擎允许您在创建索引时指定索引类型。例如:
CREATE TABLE查找(id INT)ENGINE = MEMORY; CREATE INDEX id_index ON查找(id)USING BTREE;
表13.1“每个存储引擎的索引类型”
显示了不同存储引擎支持的允许索引类型值。在列出多种索引类型的情况下,当没有给出索引类型说明符时,第一种是默认值。表中未列出的存储引擎不支持index_type索引定义中的子句。
该index_type条款不能用于FULLTEXT INDEX或SPATIAL
INDEX规格。全文索引的实现取决于存储引擎。空间索引被实现为R-tree索引。
BTREE索引由
NDB存储引擎实现为T树索引。
对于NDB表列中的索引,该USING选项仅可以为唯一索引或主键指定。
USING HASH阻止创建有序索引; 否则,在NDB表上创建唯一索引或主键会自动导致创建有序索引和散列索引,每个索引都会索引相同的一组列。
对于包含NULL表中一列或多列的
唯一索引,
NDB散列索引只能用于查找文字值,这意味着
IS [NOT] NULL条件需要对表进行全面扫描。一种解决方法是确保NULL
在此类表上使用一列或多列的唯一索引始终以包含有序索引的方式创建; 也就是说,避免
USING HASH在创建索引时使用。
如果您指定的索引类型对于给定的存储引擎无效,但另一种索引类型可供引擎在不影响查询结果的情况下使用,则引擎将使用可用的类型。解析器识别
RTREE为类型名称,但目前不能为任何存储引擎指定。
index_type在该条款被弃用之前
使用该选项; 在未来的MySQL版本中,将会删除支持使用此位置的选项。如果
在前期和后期都有选项,则最终选项适用。
ON
tbl_nameindex_type
TYPE
被公认为是一个同义词。但是,这
是首选形式。
type_nameUSING
type_nameUSING
下表显示了支持该index_type选项的存储引擎的索引特征
。
表13.2 InnoDB存储引擎索引特征
| 索引类 | 索引类型 | 存储NULL值 | 允许多个NULL值 | IS NULL扫描类型 | IS NOT NULL扫描类型 |
|---|---|---|---|---|---|
| 首要的关键 | BTREE |
没有 | 没有 | N / A | N / A |
| 独特 | BTREE |
是 | 是 | 指数 | 指数 |
| 键 | BTREE |
是 | 是 | 指数 | 指数 |
FULLTEXT |
N / A | 是 | 是 | 表 | 表 |
SPATIAL |
N / A | 没有 | 没有 | N / A | N / A |
表13.3 MyISAM存储引擎索引特性
| 索引类 | 索引类型 | 存储NULL值 | 允许多个NULL值 | IS NULL扫描类型 | IS NOT NULL扫描类型 |
|---|---|---|---|---|---|
| 首要的关键 | BTREE |
没有 | 没有 | N / A | N / A |
| 独特 | BTREE |
是 | 是 | 指数 | 指数 |
| 键 | BTREE |
是 | 是 | 指数 | 指数 |
FULLTEXT |
N / A | 是 | 是 | 表 | 表 |
SPATIAL |
N / A | 没有 | 没有 | N / A | N / A |
表13.4存储器存储引擎索引特性
| 索引类 | 索引类型 | 存储NULL值 | 允许多个NULL值 | IS NULL扫描类型 | IS NOT NULL扫描类型 |
|---|---|---|---|---|---|
| 首要的关键 | BTREE |
没有 | 没有 | N / A | N / A |
| 独特 | BTREE |
是 | 是 | 指数 | 指数 |
| 键 | BTREE |
是 | 是 | 指数 | 指数 |
| 首要的关键 | HASH |
没有 | 没有 | N / A | N / A |
| 独特 | HASH |
是 | 是 | 指数 | 指数 |
| 键 | HASH |
是 | 是 | 指数 | 指数 |
表13.5 NDB存储引擎索引特性
| 索引类 | 索引类型 | 存储NULL值 | 允许多个NULL值 | IS NULL扫描类型 | IS NOT NULL扫描类型 |
|---|---|---|---|---|---|
| 首要的关键 | BTREE |
没有 | 没有 | 指数 | 指数 |
| 独特 | BTREE |
是 | 是 | 指数 | 指数 |
| 键 | BTREE |
是 | 是 | 指数 | 指数 |
| 首要的关键 | HASH |
没有 | 没有 | 表(见注1) | 表(见注1) |
| 独特 | HASH |
是 | 是 | 表(见注1) | 表(见注1) |
| 键 | HASH |
是 | 是 | 表(见注1) | 表(见注1) |
表注:
1.如果USING HASH指定阻止创建隐式有序索引。
WITH PARSER
parser_name
该选项只能用于FULLTEXT
索引。如果全文索引和搜索操作需要特殊处理,它会将解析器插件与索引相关联。InnoDB并
MyISAM支持全文分析器插件。请参阅全文解析器插件和
第28.2.4.4节“编写全文解析器插件”了解更多信息。
COMMENT '
string'
索引定义可以包含最多1024个字符的可选注释。
该
MERGE_THRESHOLD
索引页面可以被配置为使用单独的索引中的条款
声明。例如:
index_option
COMMENTCREATE INDEX
CREATE TABLE t1(id INT); CREATE INDEX id_index ON t1(id)COMMENT'MERGE_THRESHOLD = 40';
如果索引页面的页面完整百分比低于MERGE_THRESHOLD删除行时的值或行被更新操作缩短时的
值,则
InnoDB尝试将索引页与相邻索引页合并。默认
MERGE_THRESHOLD值是50,这是以前的硬编码值。
MERGE_THRESHOLD也可以在索引级别和表级使用CREATE
TABLE和ALTER TABLE
语句进行定义。有关更多信息,请参见
第14.6.13节“为索引页配置合并阈值”。
ALGORITHM并且LOCK可能会给出子句来影响表的复制方法以及在修改索引时读取和写入表的并发性级别。它们与该ALTER TABLE陈述具有相同的含义
。有关更多信息,请参见第13.1.8节“ALTER TABLE语法”
CREATE LOGFILE GROUPlogfile_groupADD UNDOFILE'undo_file' [INITIAL_SIZE [=]initial_size] [UNDO_BUFFER_SIZE [=]undo_buffer_size] [REDO_BUFFER_SIZE [=]redo_buffer_size] [NODEGROUP [=]nodegroup_id] [等待] [评论[=]'string'] ENGINE [=]engine_name
该语句创建一个名为“ '' logfile_group的单个
UNDO文件的新日志文件组
undo_file。一个
CREATE LOGFILE GROUP陈述只有一个ADD UNDOFILE条款。有关日志文件组命名的规则,请参见
第9.2节“模式对象名称”。
所有NDB群集磁盘数据对象共享相同的名称空间。这意味着每个磁盘数据对象必须是唯一命名的(而不仅仅是给定类型的每个磁盘数据对象)。例如,您不能拥有同名的表空间和日志文件组,或者具有相同名称的表空间和数据文件。
每个NDB集群实例在任何给定时间只能有一个日志文件组。
可选INITIAL_SIZE参数设置
UNDO文件的初始大小; 如果未指定,则默认为128M(128兆字节)。可选
UNDO_BUFFER_SIZE参数设置UNDO日志文件组缓冲区使用的大小; 默认值UNDO_BUFFER_SIZE是
8M(八兆字节); 该值不能超过可用的系统内存量。这两个参数均以字节为单位指定。您可以选择遵循其中一个或两个用单字母缩写的一个数量级,这与英文中使用的缩写类似my.cnf。通常,这是字母之一M(对于兆字节)或G(对于千兆字节)。
用于存储的内存UNDO_BUFFER_SIZE来自全局池,其大小由SharedGlobalMemory数据节点配置参数的值决定
。这包括通过设置InitialLogFileGroup数据节点配置参数为此选项隐含的任何默认值
。
最大允许数量UNDO_BUFFER_SIZE为629145600(600 MB)。
在32位系统上,支持的最大值为
INITIAL_SIZE4294967296(4 GB)。(错误#29186)
最小允许值为INITIAL_SIZE1048576(1 MB)。
该ENGINE选项确定此日志文件组将使用的存储引擎,并且
engine_name是存储引擎的名称。在MySQL 5.7中,这必须是
NDB(或
NDBCLUSTER)。如果
ENGINE未设置,MySQL会尝试使用由default_storage_engine服务器系统变量(以前
storage_engine)指定的引擎
。在任何情况下,如果引擎未指定为NDB或
NDBCLUSTER,则CREATE
LOGFILE GROUP语句看起来成功,但实际上无法创建日志文件组,如下所示:
mysql>CREATE LOGFILE GROUP lg1- >ADD UNDOFILE 'undo.dat' INITIAL_SIZE = 10M;查询确定,0行受影响,1个警告(0.00秒) MySQL的>SHOW WARNINGS;+ ------- + ------ + ---------------------------------- -------------------------------------------------- ------------ + | 级别| 代码| 留言| + ------- + ------ + ---------------------------------- -------------------------------------------------- ------------ + | 错误| 1478 | 表存储引擎'InnoDB'不支持创建选项'TABLESPACE或LOGFILE GROUP' | + ------- + ------ + ---------------------------------- -------------------------------------------------- ------------ + 一排(0.00秒) mysql> 错误1529(HY000):无法删除LOGFILE GROUPDROP LOGFILE GROUP lg1 ENGINE = NDB;mysql>CREATE LOGFILE GROUP lg1- >ADD UNDOFILE 'undo.dat' INITIAL_SIZE = 10M- >ENGINE = NDB;查询OK,0行受影响(2.97秒)
事实上,在CREATE LOGFILE GROUP
非NDB存储引擎被命名但看起来成功的情况下,语句实际上不会返回错误,这是一个已知问题,我们希望在未来的NDB群集版本中解决这个问题。
REDO_BUFFER_SIZE,
NODEGROUP,WAIT,和
COMMENT被分析,但是被忽略,所以有在MySQL 5.7没有影响。这些选项旨在用于未来的扩展。
与它一起使用时ENGINE [=] NDB,将UNDO在每个群集数据节点上创建一个日志文件组和关联的日志文件。您可以UNDO通过查询INFORMATION_SCHEMA.FILES表来验证
文件是否已创建并获取有关它们的信息
。例如:
mysql>SELECT LOGFILE_GROUP_NAME, LOGFILE_GROUP_NUMBER, EXTRA- >FROM INFORMATION_SCHEMA.FILES- >WHERE FILE_NAME = 'undo_10.dat';+ -------------------- + ---------------------- + ----- ----------- + | LOGFILE_GROUP_NAME | LOGFILE_GROUP_NUMBER | EXTRA | + -------------------- + ---------------------- + ----- ----------- + | lg_3 | 11 | CLUSTER_NODE = 3 | | lg_3 | 11 | CLUSTER_NODE = 4 | + -------------------- + ---------------------- + ----- ----------- + 2排(0.06秒)
CREATE LOGFILE GROUP仅适用于NDB群集的磁盘数据存储。请参见
第21.5.13节“NDB群集磁盘数据表”。
创建
[DEFINER = { user| 当前用户 }]
程序sp_name([ proc_parameter[,...]])
[ characteristic...]routine_body
创建
[DEFINER = { user| 当前用户 }]
FUNCTION sp_name([ func_parameter[,...]])
返回type
[ characteristic...]routine_body
proc_parameter:
[IN | OUT | 进出 ]param_name type
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
评论' string'
| 语言SQL
| [不是]确定性的
| {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}
| SQL安全性{DEFINER | INVOKER}
routine_body:
Valid SQL routine statement
这些语句创建存储的例程。默认情况下,例程与默认数据库相关联。要将例程明确地与给定数据库相关联,请db_name.sp_name在创建该名称时指定该名称
。
该CREATE FUNCTION语句也用于MySQL以支持UDF(用户定义的函数)。请参见
第28.4节“向MySQL添加新功能”。UDF可以被视为外部存储功能。存储函数与UDF共享其名称空间。有关描述服务器如何解释对不同类型函数的引用的规则,请参见第9.2.4节“函数名称解析和解析”。
要调用存储过程,请使用该
CALL语句(请参见
第13.2.1节“CALL语法”)。要调用存储的函数,请在表达式中引用它。该函数在表达式评估过程中返回一个值。
CREATE PROCEDURE并
CREATE FUNCTION要求
CREATE ROUTINE特权。它们也可能需要SUPER
特权,具体取决于DEFINER值,如本节后面所述。如果启用二进制日志记录,则
CREATE FUNCTION可能需要
SUPER权限,如
第23.7节“存储程序的二进制日志记录”中所述。
默认情况下,MySQL的自动授权
ALTER ROUTINE和
EXECUTE权限,以常规的创造者。这种行为可以通过禁用automatic_sp_privileges系统变量来改变
。请参见第23.2.2节“存储例程和MySQL特权”。
如
本节后面所述,DEFINER和SQL SECURITY子句指定在例程执行时检查访问特权时要使用的安全上下文。
如果例程名称与内置SQL函数的名称相同,则会出现语法错误,除非在定义例程或稍后调用例程时在名称和下面的括号之间使用空格。由于这个原因,避免使用你自己存储的例程的现有SQL函数的名称。
在IGNORE_SPACESQL模式适用于内置的功能,而不是保存的程序。无论是否IGNORE_SPACE启用,始终允许在存储的例程名后面有空格
。
圆括号内的参数列表必须始终存在。如果没有参数,()应该使用一个空的参数列表
。参数名称不区分大小写。
每个参数IN默认都是一个参数。要指定其他参数,请使用关键字
OUT或INOUT参数名称前。
指定参数为IN,,
OUT或INOUT仅对a有效PROCEDURE。对于a
FUNCTION,参数始终被视为
IN参数。
一个IN参数传送一个值的过程。该过程可能会修改该值,但过程返回时调用程序不会看到该修改。一个OUT参数将过程中的值传回给调用者。它的初始值
NULL在过程中,当过程返回时,它的值对调用者是可见的。一个
INOUT参数是由呼叫者初始化,可以由程序进行修改,并且由所述方法制备的任何变化是可见的呼叫者时,过程返回。
对于每个OUT或INOUT
参数,在CALL调用该过程的语句中传递用户定义的变量,
以便在过程返回时可以获取其值。如果要调用从另一个存储过程或函数内的过程中,你也可以通过常规的参数或局部常规变量作为IN或
INOUT参数。
常规参数不能在程序中准备的语句中引用; 参见 第C.1节“对存储程序的限制”。
以下示例显示了一个使用OUT参数的简单存储过程
:
MySQL的>delimiter //mysql>CREATE PROCEDURE simpleproc (OUT param1 INT)- >BEGIN- >SELECT COUNT(*) INTO param1 FROM t;- >END//查询OK,0行受影响(0.00秒) MySQL的>delimiter ;MySQL的>CALL simpleproc(@a);查询OK,0行受影响(0.00秒) MySQL的>SELECT @a;+ ------ + | @a | + ------ + | 3 | + ------ + 一排(0.00秒)
该示例使用MySQL的客户机
delimiter命令语句从定界符改变;到//当正在定义的过程。这使;过程体中使用的
分隔符能够传递到服务器,而不是被mysql本身解释
。请参见
第23.1节“定义存储的程序”。
该RETURNS条款可能只针对一个
FUNCTION强制性规定。它指示函数的返回类型,并且函数体必须包含语句。如果
语句返回不同类型的值,则该值被强制为正确的类型。例如,如果函数在子句中指定了一个或
一个
值
,但该
语句返回一个整数,则函数返回的值就是成员集中对应成员的字符串。
RETURN
valueRETURNENUMSETRETURNSRETURNENUMSET
以下示例函数接受一个参数,使用SQL函数执行操作并返回结果。在这种情况下,不需要使用,delimiter
因为函数定义不包含内部
;语句分隔符:
mysql>CREATE FUNCTION hello (s CHAR(20))mysql>RETURNS CHAR(50) DETERMINISTIC- >RETURN CONCAT('Hello, ',s,'!');查询OK,0行受影响(0.00秒) MySQL的>SELECT hello('world');+ ---------------- + | hello('world')| + ---------------- + | 你好,世界!| + ---------------- + 一排(0.00秒)
可以声明参数类型和函数返回类型以使用任何有效的数据类型。该COLLATE属性可以在CHARACTER SET
属性前面使用。
该routine_body由一个有效的SQL例程语句。这可以是一个简单的语句,例如
SELECT或
INSERT,或者使用BEGIN和编写的复合语句END。复合语句可以包含声明,循环和其他控制结构语句。这些语句的语法在第13.6节“复合语句语法”中进行了描述。
MySQL允许例程包含DDL语句,例如
CREATE和DROP。MySQL还允许存储过程(但不是存储函数)包含SQL事务语句,如
COMMIT。存储函数可能不包含执行显式或隐式提交或回滚的语句。SQL标准并不要求支持这些语句,该标准规定每个DBMS供应商都可以决定是否允许这些语句。
返回结果集的语句可以在存储过程中使用,但不能在存储的函数中使用。这项禁令包括SELECT不具有的声明条款等语句,例如,
和
INTO
var_listSHOWEXPLAINCHECK TABLE。对于可以在函数定义时返回结果集的语句,会Not allowed to return a result set from a
function发生错误(ER_SP_NO_RETSET)。对于只能在运行时返回结果集的语句,会
PROCEDURE %s can't return a result set in the given
context发生错误(ER_SP_BADSELECT)。
USE存储的例程中的语句不被允许。当一个例程被调用时,一个隐式
被执行(并且在例程终止时被撤消)。例程在执行时具有给定的默认数据库的原因。对常规默认数据库以外的数据库中对象的引用应使用适当的数据库名称进行限定。
USE db_name
有关存储例程中不允许的语句的其他信息,请参见 第C.1节“存储的程序限制”。
有关从具有MySQL接口的语言编写的程序中调用存储过程的信息,请参见 第13.2.1节“CALL语法”。
MySQL存储 sql_mode当例程被创建或更改时,系统变量设置,并始终使用此设置执行例程,
而不管当例程开始执行时的当前服务器SQL模式。
在对参数进行评估并将结果值分配给例程参数之后,从调用者的SQL模式切换到例程的SQL模式。如果您在严格SQL模式下定义例程但以非严格模式调用该例程,则在严格模式下不会为常规参数分配参数。如果您要求以严格SQL模式分配传递给例程的表达式,则应该使用严格模式调用例程。
这个COMMENT特性是一个MySQL扩展,可以用来描述存储的例程。这些信息由SHOW CREATE
PROCEDURE和SHOW CREATE
FUNCTION语句显示。
该LANGUAGE特征指示例程被写入的语言。服务器忽略这个特性; 仅支持SQL例程。
的例程被认为是“ 确定性的 ”,如果它总是产生相同的结果对于相同的输入参数,并且
“ 不确定性 ”否则。如果在例程定义中既没有
DETERMINISTIC也没有NOT
DETERMINISTIC给出,则默认是NOT DETERMINISTIC。要声明一个函数是确定性的,你必须指定
DETERMINISTIC明确。
例程的性质评估基于创建者的
“ 诚实 ”:MySQL不检查声明的例程DETERMINISTIC是否没有产生非确定性结果的语句。然而,错误的例行程序可能会影响结果或影响性能。声明一个不确定的例程
DETERMINISTIC可能会导致优化器做出错误的执行计划选择,从而导致意想不到的结果。宣布一个确定性程序为
NONDETERMINISTIC可能会导致可用的优化不被使用,从而降低性能。
如果启用二进制日志记录,则该DETERMINISTIC
特征会影响MySQL接受哪些例程定义。请参见第23.7节“存储程序的二进制日志记录”。
包含NOW()
函数(或其同义词)的例程,或者
RAND()是非确定性的,但它可能仍然是复制安全的。因为
NOW(),二进制日志包含时间戳和正确复制。
RAND()只要在程序执行过程中只调用一次,它也可以正确复制。(您可以将例程执行时间戳和随机数种子视为主控和从属上相同的隐式输入。)
例程提供了有关数据使用性质的信息。在MySQL中,这些特征只是建议性的。服务器不会使用它们来约束例程将被允许执行的语句种类。
该SQL SECURITY特征可以是
DEFINER或INVOKER指定安全上下文; 也就是说,例程是使用例程DEFINER子句中指定的帐户的权限
还是调用它的用户执行。该帐户必须有权访问与该例程相关联的数据库。默认值是
DEFINER。调用该例程的用户必须具有该EXECUTE权限,DEFINER如果该例程在定义者安全上下文中执行,该用户也必须具有该权限。
该DEFINER子句指定在例程执行时检查具有该SQL SECURITY
DEFINER特征的例程的访问特权时要使用的MySQL帐户。
如果user值给出了
DEFINER条款,它应该被指定为MySQL账户
,
或
。默认
值是谁执行的用户
或
声明。这与
明确指定相同。
'user_name'@'host_name'CURRENT_USERCURRENT_USER()DEFINERCREATE PROCEDURECREATE FUNCTIONDEFINER = CURRENT_USER
如果您指定了该DEFINER子句,则这些规则将确定有效的DEFINER用户值:
如果您没有SUPER
权限,唯一允许的user
值是您自己的帐户,无论是按字面还是使用指定CURRENT_USER。您无法将定义者设置为某个其他帐户。
如果您有SUPER
权限,则可以指定任何语法上有效的帐户名称。如果该帐户不存在,则会生成警告。
尽管可以使用不存在的DEFINER帐户创建例程,
但如果该SQL SECURITY值是
DEFINER定制者帐户但不存在,则会在例程执行时发生错误。
有关存储的例程安全性的更多信息,请参见 第23.6节“用于存储的程序和视图的访问控制”。
在由SQL
SECURITY DEFINER特征定义的存储例程中,
CURRENT_USER返回该例程的
DEFINER值。有关存储例程中用户审计的信息,请参见
第6.3.12节“基于SQL的MySQL账户活动审计”。
请考虑以下过程,其中显示了mysql.user表中列出的MySQL帐户数的计数
:
CREATE DEFINER ='admin'@'localhost'PROCEDURE account_count() 开始 SELECT'账户数量:',COUNT(*)FROM mysql.user; 结束;
无论用户如何定义,
该过程都被分配一个DEFINER帐户
'admin'@'localhost'。无论哪个用户调用该帐户(因为缺省安全特征是DEFINER),它都会以该帐户的特权执行。该过程是成功还是失败,取决于调用者是否有
EXECUTE权限并
'admin'@'localhost'具有该
SELECT权限
mysql.user表。
现在假设程序是用 SQL
SECURITY INVOKER特征:
CREATE DEFINER ='admin'@'localhost'PROCEDURE account_count() SQL安全调用 开始 SELECT'账户数量:',COUNT(*)FROM mysql.user; 结束;
该过程仍具有DEFINER的
'admin'@'localhost',但在这种情况下,它与调用用户的权限执行。因此,程序成功或失败,取决于调用者是否拥有EXECUTE它的SELECT特权和特权
mysql.user表。
服务器处理例程参数的数据类型,使用DECLARE或使用函数返回值创建本地例程变量
,如下所示:
检查分配的数据类型不匹配和溢出。转换和溢出问题会导致警告或严格SQL模式下的错误。
只能标记标量值。例如,诸如SET x = (SELECT 1, 2)无效的陈述。
对于字符数据类型,如果CHARACTER
SET声明中有属性,则使用指定的字符集及其默认排序规则。如果该
COLLATE属性也存在,则使用该排序规则而不是默认排序规则。
如果CHARACTER SET和
COLLATE属性不存在,则使用在例程创建时生效的数据库字符集和排序规则。为避免服务器使用数据库字符集和归类,请为字符数据参数提供显式
CHARACTER SET和
COLLATE属性。
如果更改数据库缺省字符集或排序规则,则必须删除并重新创建使用数据库缺省值的存储例程,以便它们使用新的缺省值。
该数据库字符集和校对规则由的值给出
character_set_database和
collation_database系统变量。有关更多信息,请参见
第10.3.3节“数据库字符集和归类”。
CREATE SERVERserver_nameFOREIGN DATA WRAPPERwrapper_nameOPTIONS(option[,option] ...)option: {主机character-literal| DATABASEcharacter-literal| USERcharacter-literal| 密码character-literal| SOCKETcharacter-literal| 所有者character-literal| 港口numeric-literal}
该语句创建用于FEDERATED存储引擎的服务器的定义
。该CREATE
SERVER语句servers在mysql
数据库的表中创建一个新行
。该声明需要
SUPER特权。
本
应该是唯一的参考服务器。服务器定义在服务器范围内是全局的,不可能将服务器定义限定到特定的数据库。
server_name最大长度为64个字符(大于64个字符的名称将被自动截断),并且不区分大小写。您可以将该名称指定为带引号的字符串。
server_name
该
应wrapper_namemysql,并且可以用单引号引起来。其他值
目前不支持。
wrapper_name
对于每一个你必须指定一个字符文字或数字文字。字符文字是UTF-8,支持最大长度为64个字符,默认为空白(空)字符串。字符串文字被无提示地截断为64个字符。数字文字必须是介于0和9999之间的数字,默认值为0。
option
该OWNER选项当前未应用,并且不会影响创建的服务器连接的所有权或操作。
该CREATE SERVER语句在mysql.servers表中创建一个条目,稍后可以CREATE TABLE在创建FEDERATED表时使用该语句。您指定的选项将用于填充mysql.servers表格中的列
。该表包括
Server_name,Host,
Db,Username,
Password,Port和
Socket。
例如:
CREATE SERVER FOREIGN DATA WRAPPER mysql 选项(USER'Remote',HOST'198.51.100.106',DATABASE'test');
务必指定建立到服务器的连接所需的全部选项。用户名,主机名和数据库名称是强制性的。其他选项也可能需要,例如密码。
创建与FEDERATED表格的连接时,可以使用存储在表格中的数据:
CREATE TABLE t(s1 INT)ENGINE = FEDERATED CONNECTION ='s';
有关更多信息,请参见 第15.8节“FEDERATED存储引擎”。
CREATE SERVER导致隐式提交。请参见
第13.3.3节“导致隐式提交的语句”。
CREATE SERVER 不写入二进制日志,不管正在使用的日志格式如何。
CREATE [TEMPORARY] TABLE [IF NOT EXISTS]tbl_name(create_definition,...) [table_options] [partition_options] CREATE [TEMPORARY] TABLE [IF NOT EXISTS]tbl_name[(create_definition,...)] [table_options] [partition_options] [IGNORE | 更换] [如]query_expressionCREATE [TEMPORARY] TABLE [如果不存在]tbl_name{LIKEold_tbl_name| (LIKEold_tbl_name)}create_definition: | [CONSTRAINT [ ]] PRIMARY KEY [ ](col_namecolumn_definitionsymbolindex_typeindex_col_name,...) [index_option] ... | {INDEX | KEY} [index_name] [index_type](index_col_name,...) [index_option] ... | [CONSTRAINT [symbol]] UNIQUE [INDEX | KEY] [index_name] [index_type](index_col_name,...) [index_option] ... | {FULLTEXT | SPATIAL} [INDEX | KEY] [index_name](index_col_name,...) [index_option] ... | [CONSTRAINT [symbol]] FOREIGN KEY [index_name](index_col_name,...)reference_definition| CHECK(expr)column_definition:data_type[NOT NULL | NULL] [默认default_value] [AUTO_INCREMENT] [UNIQUE [KEY]] [[PRIMARY] KEY] [评论'string'] [COLUMN_FORMAT {FIXED | DYNAMIC | DEFAULT}] [存储{磁盘|存储器|默认}] [reference_definition] |data_type[GENERATED ALWAYS] AS(expression) [VIRTUAL | STORED] [NOT NULL | 空值] [独特[KEY]] [[PRIMARY] KEY] [评论'string']data_type: BIT [(length)] | TINYINT [(length)] [UNSIGNED] [ZEROFILL] | SMALLINT [(length)] [UNSIGNED] [ZEROFILL] | MEDIUMINT [(length)] [UNSIGNED] [ZEROFILL] | INT [(length)] [UNSIGNED] [ZEROFILL] | INTEGER [(length)] [UNSIGNED] [ZEROFILL] | BIGINT [(length)] [UNSIGNED] [ZEROFILL] | REAL [(length,decimals)] [UNSIGNED] [ZEROFILL] | DOUBLE [(length,decimals)] [UNSIGNED] [ZEROFILL] | FLOAT [(length,decimals)] [UNSIGNED] [ZEROFILL] | DECIMAL [(length[,decimals])] [UNSIGNED] [ZEROFILL] | NUMERIC [(length[,decimals])] [UNSIGNED] [ZEROFILL] | 日期 | TIME [(fsp)] | TIMESTAMP [(fsp)] | DATETIME [(fsp)] | 年 | CHAR [(length)] [字符集charset_name] [COLLATEcollation_name] | VARCHAR(length) [字符集charset_name] [COLLATEcollation_name] | BINARY [(length)] | VARBINARY(length) | TINYBLOB | BLOB [(length)] | MEDIUMBLOB | LONGBLOB | TINYTEXT [字符集charset_name] [COLLATEcollation_name] | TEXT [(length)] [字符集charset_name] [COLLATEcollation_name] | MEDIUMTEXT [字符集charset_name] [COLLATEcollation_name] | LONGTEXT [字符集charset_name] [COLLATEcollation_name] | ENUM( ,,value1,...)value2value3[字符集charset_name] [COLLATEcollation_name] | SET( ,,value1,...)value2value3[字符集charset_name] [COLLATEcollation_name] | JSON |spatial_typeindex_col_name:col_name[(length)] [ASC | DESC]index_type: 使用{BTREE | HASH}index_option: KEY_BLOCK_SIZE [=]value|index_type| 与PARSERparser_name| 评论'string'reference_definition: 参考文献tbl_name(index_col_name,...) [匹配完整| MATCH PARTIAL | MATCH SIMPLE] [在删除reference_option] [在更新reference_option]reference_option: RESTRICT | CASCADE | SET NULL | NO ACTION | 默认设置table_options:table_option[[,]table_option] ...table_option: AUTO_INCREMENT [=]value| AVG_ROW_LENGTH [=]value| [DEFAULT] CHARACTER SET [=]charset_name| CHECKSUM [=] {0 | 1} | [DEFAULT] COLLATE [=]collation_name| 评论[=]'string' | COMPRESSION [=] {'ZLIB'|'LZ4'|'NONE'} | CONNECTION [=]'connect_string' | {DATA | INDEX} DIRECTORY [=]'absolute path to directory' | DELAY_KEY_WRITE [=] {0 | 1} | ENCRYPTION [=] {'Y'| 'N'} | ENGINE [=]engine_name| INSERT_METHOD [=] {NO | FIRST | LAST} | KEY_BLOCK_SIZE [=]value| MAX_ROWS [=]value| MIN_ROWS [=]value| PACK_KEYS [=] {0 | 1 | 默认} | PASSWORD [=]'string' | ROW_FORMAT [=] {默认|动态|固定|压缩|冗余|精简} | STATS_AUTO_RECALC [=] {DEFAULT | 0 | 1} | STATS_PERSISTENT [=] {DEFAULT | 0 | 1} | STATS_SAMPLE_PAGES [=]value| TABLESPACEtablespace_name[STORAGE {DISK | MEMORY | DEFAULT}] | UNION [=](tbl_name[,tbl_name] ...)partition_options: PARTITION BY {[LINEAR] HASH(expr) | [LINEAR] KEY [ALGORITHM = {1 | 2}](column_list) | 范围{(expr)| COLUMNS(column_list)} | LIST {(expr)| COLUMNS(column_list)}} [PARTITIONSnum] [SUBPARTITION BY {[LINEAR] HASH(expr) | [LINEAR] KEY [ALGORITHM = {1 | 2}](column_list)} [SUBPARTITIONSnum] ] [(partition_definition[,partition_definition] ...)]partition_definition: 划分partition_name[VALUES {小于{(expr|value_list)| MAXVALUE} | IN(value_list)}] [[STORAGE] ENGINE [=]engine_name] [评论[=]'string'] [DATA DIRECTORY [=]''] [INDEX DIRECTORY [=]'data_dir'] [MAX_ROWS [=]index_dirmax_number_of_rows] [MIN_ROWS [=]min_number_of_rows] [TABLESPACE [=] tablespace_name] [(subpartition_definition[,subpartition_definition] ...)]subpartition_definition: SUBPARTITIONlogical_name[[STORAGE] ENGINE [=]engine_name] [评论[=]'string'] [DATA DIRECTORY [=]''] [INDEX DIRECTORY [=]'data_dir'] [MAX_ROWS [=]index_dirmax_number_of_rows] [MIN_ROWS [=]min_number_of_rows] [TABLESPACE [=] tablespace_name]query_expression:SELECT ...(Some valid select or union statement)
CREATE TABLE用给定的名字创建一个表格。你必须拥有CREATE桌子的
特权。
默认情况下,表使用默认数据库创建
InnoDB存储引擎。如果表存在,如果没有默认数据库,或者数据库不存在,则会发生错误。
有关表的物理表示的信息,请参见 第13.1.18.2节“由CREATE TABLE创建的文件”。
原始CREATE TABLE
语句,包括所有规范和表格选项,在创建表格时由MySQL存储。有关更多信息,请参见第13.1.18.1节“CREATE TABLE语句保留”。
该CREATE
TABLE声明有几个方面,在本节中的以下主题下进行介绍:
tbl_name
表名可以指定为
db_name.tbl_name在特定数据库中创建表。无论是否有默认数据库,假设数据库存在,这都可以工作。如果您使用带引号的标识符,请分别引用数据库和表名称。例如,写
`mydb`.`mytbl`,而不是
`mydb.mytbl`。
第9.2节“模式对象名称” 给出了允许的表名称规则 。
IF NOT EXISTS
如果表存在,防止发生错误。但是,没有验证现有表的结构与CREATE TABLE陈述中指出的结构相同
。
TEMPORARY创建表格时
可以使用关键字。一个TEMPORARY表只在当前会话中可见,而当会话关闭时自动删除。有关更多信息,请参见
第13.1.18.3节“CREATE TEMPORARY TABLE语法”。
LIKE
用于CREATE TABLE ... LIKE根据另一个表的定义(包括原始表中定义的所有列属性和索引)创建一个空表:
CREATE TABLEnew_tblLIKEorig_tbl;
有关更多信息,请参见第13.1.18.4节“CREATE TABLE ... LIKE语法”。
[AS]
query_expression
要从另一个表创建一个表,请在SELECT语句末尾添加一条
CREATE TABLE语句:
CREATE TABLEnew_tblAS SELECT * FROMorig_tbl;
有关更多信息,请参见 第13.1.18.5节“CREATE TABLE ... SELECT语法”。
IGNORE|REPLACE
在IGNORE和REPLACE
选项指示如何处理使用复制表时复制唯一键值的行
SELECT声明。
有关更多信息,请参见 第13.1.18.5节“CREATE TABLE ... SELECT语法”。
每个表格有4096列的硬限制,但对于给定表格,有效最大值可能较小,并取决于第C.10.4节“表列数量和行大小限制”中讨论的因素。
data_type
data_type表示列定义中的数据类型。
spatial_type代表一种空间数据类型。显示的数据类型语法仅供参考。有关指定列数据类型的可用语法的完整说明以及有关每种类型属性的信息,请参阅第11章数据类型和
第11.5节“空间数据类型”。从MySQL 5.7.8开始,
JSON表列也支持数据类型; 有关更多信息,请参见第11.6节“JSON数据类型”。
某些属性不适用于所有数据类型。
AUTO_INCREMENT仅适用于整数和浮点类型。DEFAULT并不适用于BLOB,
TEXT,
GEOMETRY,和
JSON类型。
字符数据类型(CHAR,
VARCHAR,
TEXT)可以包括
CHARACTER SET和
COLLATE属性来指定该列的字符集和归类。有关详细信息,请参见第10章,字符集,归类,Unicode。CHARSET
是一个同义词CHARACTER SET。例:
CREATE TABLE t(c CHAR(20)CHARACTER SET utf8 COLLATE utf8_bin);
为CHAR,
VARCHAR,
BINARY,和
VARBINARY列,索引可以创建仅使用列值的前导部分,使用
语法来指定一个索引前缀长度。
和
列也可以被索引,但前缀长度必须给出。对于非二进制字符串类型,前缀长度以字符给出,二进制字符串类型以字节给出。即,索引项由所述第一的
每个列的值的字符,
和
col_name(length)BLOBTEXTlengthCHARVARCHARTEXT列,并且所述第一
length对每个列的值的字节BINARY,
VARBINARY和
BLOB列。只索引像这样的列值的前缀可以使索引文件小得多。有关索引前缀的更多信息,请参见第13.1.14节“CREATE INDEX语法”。
只有InnoDB与
MyISAM上存储引擎支持索引BLOB和
TEXT列。例如:
CREATE TABLE测试(blob_col BLOB,INDEX(blob_col(10)));
从MySQL 5.7.17开始,如果指定的索引前缀超过最大列数据类型大小,则按
CREATE TABLE如下所示处理索引:
对于非唯一索引,如果发生错误(如果启用严格SQL模式),或者索引长度降低到位于最大列数据类型大小范围内并产生警告(如果严格模式未启用)。
对于唯一索引,无论SQL模式如何都会发生错误,因为减少索引长度可能会导致插入不符合指定唯一性要求的非唯一条目。
JSON列不能被索引。您可以通过在生成的列上创建索引来解决此限制,该JSON列从列中提取标量值。有关详细示例,请参阅
索引生成的列以提供JSON列索引。
NOT NULL | NULL
如果既没有NULL也没有NOT
NULL被指定,该列被视为
NULL已被指定。
在MySQL 5.7中,只有InnoDB,
MyISAM以及MEMORY
在可以有列存储引擎支持索引
NULL值。在其他情况下,您必须声明索引列NOT NULL或错误结果。
DEFAULT
指定列的默认值。有一个例外,默认值必须是常数; 它不能是一个函数或表达式。这意味着,例如,您不能将日期列的默认值设置为诸如NOW()or
之类的函数的值CURRENT_DATE。例外情况是您可以将其指定
CURRENT_TIMESTAMP为a TIMESTAMP或
DATETIME列的默认值。请参见
第11.3.5节“自动初始化和更新TIMESTAMP和DATETIME”。
如果列定义不包含显式
DEFAULT值,则MySQL将按照第11.7节“数据类型默认值”中所述确定默认值。
如果启用NO_ZERO_DATE或
NO_ZERO_IN_DATESQL模式并且根据该模式默认日期值不正确,CREATE TABLE
则在严格SQL模式未启用时会生成警告,如果启用严格模式则会生成错误。例如,
NO_ZERO_IN_DATE启用后
c1 DATE DEFAULT '2010-00-00'会产生警告。
AUTO_INCREMENT
整数或浮点列可以具有附加属性AUTO_INCREMENT。当您插入NULL(推荐)的值或
0插入索引
AUTO_INCREMENT列时,该列将设置为下一个序列值。通常这是
,value+1value表中当前列的最大值在哪里
。
AUTO_INCREMENT序列开头
1。
要AUTO_INCREMENT在插入行后检索值,请使用
LAST_INSERT_ID()SQL函数或mysql_insert_id()C API函数。请参见第12.14节“信息函数”和
第27.8.7.38节“mysql_insert_id()”。
如果NO_AUTO_VALUE_ON_ZERO
启用了SQL模式,则可以0按AUTO_INCREMENT列
存储,
0而不会生成新的序列值。请参见第5.1.8节“服务器SQL模式”。
AUTO_INCREMENT每个表
只能有一列,它必须被编入索引,并且不能有
DEFAULT值。AUTO_INCREMENT仅当列仅包含正值时,该
列才能正常工作。插入一个负数被认为是插入一个非常大的正数。这样做是为了避免精度问题,当数
“ 包裹 ”从正到负,还要确保您不会意外得到一个
AUTO_INCREMENT包含列
0。
对于MyISAM表格,您可以AUTO_INCREMENT在多列键中指定
辅助列。参见
第3.6.9节“使用AUTO_INCREMENT”。
要使MySQL与某些ODBC应用程序兼容,可以AUTO_INCREMENT使用以下查询找到最后一个插入行的值:
SELECT * FROMtbl_nameWHEREauto_col是NULL
此方法要求
sql_auto_is_null变量未设置为0.请参见第5.1.5节“服务器系统变量”。
有关信息InnoDB,并
AUTO_INCREMENT请参见
第14.8.1.5,“AUTO_INCREMENT InnoDB的处理”。有关AUTO_INCREMENT和MySQL复制的信息,请参见
第16.4.1.1节“复制和AUTO_INCREMENT”。
COMMENT
可以使用该COMMENT选项指定列的注释
,最长可达1024个字符。该评论由SHOW
CREATE TABLE和
SHOW FULL
COLUMNS语句显示。
COLUMN_FORMAT
在NDB簇,它也可以指定的各个列的数据存储格式
NDB使用表
COLUMN_FORMAT。允许列格式FIXED,DYNAMIC以及
DEFAULT。FIXED用于指定固定宽度存储,DYNAMIC
允许DEFAULT列为可变宽度,
并使列使用固定宽度或可变宽度存储(由列的数据类型(可能由ROW_FORMAT指定符覆盖
)确定)。
从MySQL NDB Cluster 7.5.4开始,对于
NDB表,COLUMN_FORMATis 的缺省值
FIXED。(DYNAMIC
在MySQL NDB Cluster 7.5.1中已将默认设置切换到此状态,但此更改已恢复,以保持与现有GA版本系列的向后兼容性。)(错误#24487363)
COLUMN_FORMAT目前对使用存储引擎以外的表的列不起作用
NDB。在MySQL 5.7和更高版本中,它COLUMN_FORMAT被默默忽略。
STORAGE
对于NDB表,可以通过使用STORAGE子句来指定列是存储在磁盘上还是存储在内存中。STORAGE
DISK导致该列存储在磁盘上,并
STORAGE MEMORY导致使用内存中的存储。所CREATE TABLE
使用的声明必须包含一个
TABLESPACE条款:
mysql>CREATE TABLE t1 (- >c1 INT STORAGE DISK,- >c2 INT STORAGE MEMORY- > ERROR 1005(HY000):无法创建'c.t1'表(errno:140)) ENGINE NDB;mysql>CREATE TABLE t1 (- >c1 INT STORAGE DISK,- >c2 INT STORAGE MEMORY- >) TABLESPACE ts_1 ENGINE NDB;查询OK,0行受影响(1.06秒)
对于NDB表,STORAGE
DEFAULT相当于STORAGE
MEMORY。
该STORAGE子句对使用存储引擎以外的表无效
NDB。该
STORAGE关键字仅在NDB集群提供的mysqld版本中受支持; 它在任何其他版本的MySQL中都无法识别,任何使用该STORAGE
关键字的尝试都会导致语法错误。
GENERATED ALWAYS
用于指定生成的列表达式。有关生成列的信息,请参见 第13.1.18.8节“CREATE TABLE和Generated Columns”。
存储的生成列可以编入索引。InnoDB
支持虚拟生成列上的二级索引
。请参见
第13.1.18.9节“二级索引和生成的列”。
CONSTRAINT
symbol
如果给出该子句,则该值(如果使用)在数据库中必须是唯一的。重复会
导致错误。如果没有给出该子句,或者在
关键字之后没有包含a,则会自动创建约束的名称。
CONSTRAINT
symbolsymbolsymbolsymbolCONSTRAINT
PRIMARY KEY
一个唯一索引,其中所有键列必须定义为
NOT NULL。如果它们没有被明确声明为NOT NULL,则MySQL会隐式地声明它们(并且默默地)。一张桌子只能有一个
PRIMARY KEY。a的名称PRIMARY
KEY总是PRIMARY,因此不能用作任何其他类型索引的名称。
如果你没有PRIMARY KEY和应用程序要求PRIMARY KEY在你的表中,MySQL返回第一个UNIQUE
没有NULL列的
索引PRIMARY KEY。
在InnoDB表中,保持PRIMARY
KEY简短以最小化二级索引的存储开销。每个二级索引条目都包含相应行的主键列的副本。(请参见
第14.8.2.1节“集群索引和二级索引”。)
在创建的表中,PRIMARY KEY首先放置a ,然后放置所有UNIQUE
索引,然后放置非唯一索引。这有助于MySQL优化器优先使用哪个索引,并且更快速地检测重复UNIQUE密钥。
A PRIMARY KEY可以是多列索引。但是,您无法使用PRIMARY KEY列规范中的键属性创建多列索引。这样做只会将单个列标记为主要列。您必须使用单独的
条款。
PRIMARY
KEY(index_col_name, ...)
如果a PRIMARY KEY仅包含一个具有整数类型的列,则还可以像_rowid在
SELECT语句中那样引用该列。
在MySQL中,a的名字PRIMARY KEY是
PRIMARY。对于其他指标,如果不指定一个名称,该指数被分配相同的名称作为第一个索引列,有一个可选的后缀(_2,_3,
...),以使其独特。您可以使用查看表格的索引名称。请参见
第13.7.5.22节“SHOW INDEX语法”。
SHOW INDEX FROM
tbl_name
KEY | INDEX
KEY通常是一个同义词
INDEX。关键属性PRIMARY
KEY也可以
KEY在列定义中给出时指定。这是为了与其他数据库系统兼容而实现的。
UNIQUE
一个UNIQUE索引创建的约束,使得该指数的所有值必须是不同的。如果尝试使用与现有行匹配的键值添加新行,则会发生错误。对于所有引擎,UNIQUE
索引允许NULL包含多个列的值NULL。如果您为UNIQUE索引中的列指定前缀值
,则列值在前缀中必须是唯一的。
如果一个UNIQUE索引只包含一个具有整数类型的列,那么您也可以_rowid在
SELECT语句中引用该列。
FULLTEXT
一个FULLTEXT指标是用于全文搜索索引的一种特殊类型。只有
InnoDB和
MyISAM存储引擎支持
FULLTEXT索引。他们只能从创建CHAR,
VARCHAR和
TEXT列。索引总是发生在整个列上; 列前缀索引不受支持,并且如果指定,则任何前缀长度都将被忽略。有关操作的详细信息,请参见
第12.9节“全文搜索功能”。一个
WITH PARSER子句可以被指定为一个
index_option值,以便在全文索引和搜索操作需要特殊处理时将分析器插件与索引相关联。该子句仅对FULLTEXT索引有效。双方
InnoDB并
MyISAM支持全文解析器插件。请参阅全文解析器插件和
第28.2.4.4节“编写全文解析器插件”了解更多信息。
SPATIAL
您可以创建SPATIAL空间数据类型的索引。空间类型只支持
MyISAM和InnoDB
表,索引列必须声明为NOT
NULL。请参见第11.5节“空间数据类型”。
FOREIGN KEY
MySQL支持外键,它允许您在表中交叉引用相关数据,并支持外键约束,这有助于保持这种扩展数据的一致性。有关定义和选项信息,请参阅
reference_definition和
reference_option。
使用InnoDB存储引擎的分区表
不支持外键。有关更多信息,请参见
第22.6节“分区的限制和限制”。
CHECK
该CHECK子句已解析,但被所有存储引擎忽略。请参见
第1.8.2.3节“外键差异”。
index_col_name
的index_col_name规格可以与结束ASC或
DESC。这些关键字可用于将来的扩展,用于指定升序或降序索引值存储。目前,他们被解析但被忽略; 索引值始终以升序存储。
如果
启用该选项
,则由length
属性定义的前缀对于InnoDB表可以最多767个字节,对于3072个字节可以最多7个
字节
innodb_large_prefix。对于MyISAM表,前缀限制为1000字节。
前缀限制以字节为单位,而在前缀长度CREATE TABLE,
ALTER TABLE和
CREATE INDEX语句被解释为非二进制串类型的字符数(CHAR,
VARCHAR,
TEXT二进制串类型()和字节数BINARY,
VARBINARY,
BLOB)。为使用多字节字符集的非二进制字符串列指定前缀长度时,请考虑这一点。
index_type
某些存储引擎允许您在创建索引时指定索引类型。index_type说明符的语法
是
。
USING type_name
例:
CREATE TABLE查找 (id INT,INDEX USING BTREE(id)) ENGINE = MEMORY;
首选的位置USING是在索引列表之后。它可以在列列表之前给出,但支持使用该位置的选项已被弃用,并且将在未来的MySQL版本中被删除。
index_option
index_option 值指定了索引的其他选项。
KEY_BLOCK_SIZE
对于MyISAM表,
KEY_BLOCK_SIZE可选地指定用于索引关键字块的字节大小。该值被视为提示; 如有必要,可以使用不同的尺寸。KEY_BLOCK_SIZE为单个索引定义指定的值将覆盖表级别的KEY_BLOCK_SIZE值。
有关表级
KEY_BLOCK_SIZE属性的信息,请参阅
表选项。
WITH PARSER
该WITH PARSER选项只能与FULLTEXT索引一起使用。如果全文索引和搜索操作需要特殊处理,它会将解析器插件与索引相关联。双方
InnoDB并
MyISAM支持全文解析器插件。如果您有一个
MyISAM带有关联全文分析器插件的表,则可以将该表转换为InnoDB使用ALTER
TABLE。
COMMENT
在MySQL 5.7中,索引定义可以包含最多1024个字符的可选注释。
您可以InnoDB
MERGE_THRESHOLD使用该index_optionCOMMENT子句设置单个索引的值
。请参见
第14.6.13节“为索引页面配置合并阈值”。
有关允许index_option值的更多信息
,请参见
第13.1.14节“CREATE INDEX语法”。有关索引的更多信息,请参见第8.3.1节“MySQL如何使用索引”。
有关reference_definition语法详细信息和示例,请参见
第13.1.18.6节“使用FOREIGN KEY约束”。有关特定于外键的信息InnoDB,请参见
第14.8.1.6节“InnoDB和FOREIGN KEY约束”。
InnoDB和
NDB表支持检查外键约束。被引用表的列必须始终显式命名。无论ON
DELETE和ON UPDATE外键的行动的支持。有关更多详细信息和示例,请参见第13.1.18.6节“使用FOREIGN KEY约束”。有关特定于外键的信息
InnoDB,请参见
第14.8.1.6节“InnoDB和FOREIGN KEY约束”。
对于其它存储引擎,MySQL服务器解析,而忽略
FOREIGN KEY和
REFERENCES语法的
CREATE TABLE语句。请参见
第1.8.2.3节“外键差异”。
对于熟悉ANSI / ISO SQL标准的用户,请注意,包括的任何存储引擎都不能
InnoDB识别或强制执行MATCH参照完整性约束定义中使用的
子句。显式MATCH子句的使用
不具有指定的效果,并且原因ON DELETE和
ON UPDATE子句被忽略。由于这些原因,MATCH应避免指定。
MATCHSQL标准中
的子句控制NULL与主键进行比较时如何处理组合(多列)外键中的值。InnoDB基本上实现了由其定义的语义MATCH
SIMPLE,这允许外键全部或部分NULL。在这种情况下,允许插入包含这样的外键的(子表)行,并且不与引用的(父)表中的任何行匹配。使用触发器可以实现其他语义。
另外,MySQL要求对引用的列进行索引以获得性能。但是,InnoDB
不强制要求声明引用的列UNIQUE或NOT
NULL。对包含NULL
值的非唯一键或键的外键引用的处理,对于诸如UPDATE或的操作没有很好的定义
DELETE
CASCADE。建议您使用仅引用UNIQUE
(或PRIMARY)和()的键的外键NOT
NULL。
MySQL解析但忽略了“ 内联
REFERENCES规范 ”(在SQL标准中定义),其中引用被定义为列规范的一部分。MySQL REFERENCES仅在作为单独FOREIGN KEY
规范的一部分指定时才接受
子句。
有关信息RESTRICT,
CASCADE,SET NULL,
NO ACTION,和SET
DEFAULT选项,请参阅
第13.1.18.6,“使用外键约束”。
表选项用于优化表的行为。在大多数情况下,你不必指定任何一个。除非另有说明,这些选项适用于所有存储引擎。不适用于给定存储引擎的选项可能会被接受并记忆为表定义的一部分。如果稍后您使用ALTER TABLE
该表转换表以使用不同的存储引擎,则此类选项适用。
ENGINE
使用下表中显示的名称之一指定表的存储引擎。引擎名称可以不加引号或引用。引用的名称
'DEFAULT'被识别,但被忽略。
| 存储引擎 | 描述 |
|---|---|
InnoDB |
具有行锁定和外键的事务安全表。新表的默认存储引擎。如果你有MySQL的经验但是新手,
请参阅
第14章InnoDB存储引擎,尤其是第14.1节“InnoDB入门”InnoDB。 |
MyISAM |
主要用于只读或读取主要工作负载的二进制便携式存储引擎。请参见 第15.2节“MyISAM存储引擎”。 |
MEMORY |
此存储引擎的数据仅存储在内存中。请参见 第15.3节“内存存储引擎”。 |
CSV |
以逗号分隔值格式存储行的表格。请参见 第15.4节“CSV存储引擎”。 |
ARCHIVE |
归档存储引擎。请参见 第15.5节“ARCHIVE存储引擎”。 |
EXAMPLE |
示例引擎。请参见第15.9节“示例存储引擎”。 |
FEDERATED |
访问远程表的存储引擎。请参见 第15.8节“联邦存储引擎”。 |
HEAP |
这是一个同义词MEMORY。 |
MERGE |
集合MyISAM表作为一个表。也被称为MRG_MyISAM。请参见
第15.7节“MERGE存储引擎”。 |
NDB |
集群,容错,基于内存的表,支持事务和外键。也被称为
NDBCLUSTER。请参见
第21章,MySQL NDB Cluster 7.5和NDB Cluster 7.6。 |
默认情况下,如果指定的存储引擎不可用,则语句会失败并显示错误。您可以通过NO_ENGINE_SUBSTITUTION从服务器SQL模式中删除(请参阅第5.1.8节“服务器SQL模式”)来覆盖此行为,
以便MySQL允许使用默认存储引擎替换指定的引擎。通常在这种情况下,这是
系统变量InnoDB的默认值default_storage_engine。当
NO_ENGINE_SUBSTITUTION禁用时,如果存储引擎规范未得到遵守,则会发生警告。
AUTO_INCREMENT
AUTO_INCREMENT表格
的初始值。在MySQL 5.7,这个工程的
MyISAM,MEMORY,
InnoDB,和ARCHIVE
表格。要为不支持AUTO_INCREMENT表格选项的引擎设置第一个自动增量值,请在创建表格后插入一个“ 虚拟 ”行,其值小于所需值,然后删除虚拟行。
对于AUTO_INCREMENT
在CREATE TABLE
语句中支持表格选项的引擎,您还可以使用重置
值。该值不能低于当前列中的最大值。
ALTER TABLE
tbl_name AUTO_INCREMENT =
NAUTO_INCREMENT
AVG_ROW_LENGTH
表格的平均行长度的近似值。您只需为具有可变大小行的大表设置此值。
当你创建一个MyISAM表时,MySQL使用MAX_ROWS和
AVG_ROW_LENGTH选项的乘积来决定结果表的大小。如果您未指定任一选项,则MyISAM数据和索引文件的最大大小默认为256TB。(如果您的操作系统不支持大文件,则表大小受到文件大小限制的限制。)如果您想要缩小指针大小以使索引变得更小更快,并且您不需要大文件,那么您可以通过设置myisam_data_pointer_size
系统变量来减少默认的指针大小
。(请参见
第5.1.5节“服务器系统变量”)如果你希望你所有的表能够增长到默认的限制以上,并且愿意让你的表比所需的稍微慢一些,你可以通过设置这个变量来增加默认的指针大小。将该值设置为7可以使表格尺寸达到65,536TB。
[DEFAULT] CHARACTER SET
为表指定一个默认字符集。
CHARSET是一个同义词CHARACTER
SET。如果字符集名称是
DEFAULT,则使用数据库字符集。
CHECKSUM
如果您希望MySQL为所有行保留实时校验和(即,MySQL随表更改而自动更新的校验和),请将其设置为1。这会使表更新速度稍慢,但也更容易找到损坏的表。该CHECKSUM
TABLE声明报告校验和。(MyISAM只)。
[DEFAULT] COLLATE
指定表的默认排序规则。
COMMENT
表格的评论,长达2048个字符。
您可以InnoDB
MERGE_THRESHOLD使用该table_optionCOMMENT子句设置表的值
。请参见
第14.6.13节“为索引页面配置合并阈值”。
设置NDB_TABLE选项。
在MySQL NDB簇7.5.2或更高版本,在表评论
CREATE TABLE或
ALTER TABLE声明也可以用于指定一到四个
NDB_TABLE选项
NOLOGGING,
READ_BACKUP,
PARTITION_BALANCE,或
FULLY_REPLICATED为一组名称-值对,用逗号隔开如果需要立即,跟着NDB_TABLE=开始引用评论文本的字符串。此处显示使用此语法的示例语句(强调文本):
CREATE TABLE t1(
c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
c2 VARCHAR(100),
c3 VARCHAR(100))
ENGINE = NDB
COMMENT =“NDB_TABLE = READ_BACKUP = 0,PARTITION_BALANCE = FOR_RP_BY_NODE” ;
引用字符串内不允许有空格。该字符串不区分大小写。
注释显示为输出的一部分
SHOW CREATE TABLE。注释的文本也可以作为MySQL Information Schema TABLES表的TABLE_COMMENT列
。
该评论语法也支持
表格的ALTER TABLE语句
NDB。请记住,使用的表格注释会ALTER TABLE替换表格可能已经过的任何现有注释。
MERGE_THRESHOLD表中不支持
设置表注释中的选项NDB
(忽略)。
有关完整的语法信息和示例,请参见 第13.1.18.10节“设置NDB_TABLE选项”。
COMPRESSION
用于InnoDB表格页面级压缩的压缩算法
。支持的值包括
Zlib,LZ4,和
None。该COMPRESSION
属性是通过透明页面压缩功能引入的。页面压缩仅支持
InnoDB驻留在
每个表文件表
空间中的表,并且仅在支持稀疏文件和打孔的Linux和Windows平台上可用。有关更多信息,请参见
第14.9.2节“InnoDB页面压缩”。
CONNECTION
FEDERATED
表
的连接字符串。
较早版本的MySQL使用COMMENT
连接字符串的选项。
DATA DIRECTORY, INDEX
DIRECTORY
因为InnoDB该
选项允许您
在MySQL数据目录之外创建文件每表的表空间。在您指定的目录中,MySQL创建一个与数据库名相对应的子目录,并在该目录中创建一个文件。在
配置选项必须能够使用与选项。必须指定完整的目录路径。有关更多信息,请参见
第14.7.5节“在数据目录之外创建每个文件表空间”。
DATA
DIRECTORY='directory'InnoDB.ibdinnodb_file_per_tableDATA
DIRECTORYInnoDB
创建MyISAM表格时,可以使用
子句,
子句或两者。它们分别指定放置
表的数据文件和索引文件的位置。与表格不同,当创建带有
或选项的表格时,MySQL不会创建与数据库名称相对应的子目录。文件在指定的目录中创建。
DATA
DIRECTORY='directory'INDEX
DIRECTORY='directory'MyISAMInnoDBMyISAMDATA DIRECTORYINDEX
DIRECTORY
从MySQL 5.7.17开始,您必须有权
FILE使用
DATA DIRECTORYor INDEX
DIRECTORY表选项。
分区表中的
表级DATA DIRECTORY和
INDEX DIRECTORY选项被忽略。(错误#32091)
这些选项仅在不使用该--skip-symbolic-links
选项时才起作用
。您的操作系统还必须具有工作线程安全的realpath()呼叫。有关更多完整信息,请参见
第8.12.3.2节“在Unix上使用MyISAM表的符号链接”。
如果MyISAM没有DATA DIRECTORY选项创建表
,则该
.MYD文件将在数据库目录中创建。默认情况下,如果在这种情况下MyISAM找到现有.MYD文件,它将覆盖它。这同样适用于.MYI
没有INDEX
DIRECTORY选项创建的表的文件。要抑制此行为,请使用该--keep_files_on_create选项启动服务器
,在这种情况下,MyISAM不会覆盖现有文件,而是返回错误。
如果MyISAM使用DATA DIRECTORYor INDEX
DIRECTORY选项创建表
并找到现有
.MYD或.MYI文件,MyISAM将始终返回错误。它不会覆盖指定目录中的文件。
您不能使用包含带有DATA DIRECTORYor
的MySQL数据目录的路径名称INDEX DIRECTORY。这包括分区表和个别表分区。(见Bug#32167。)
DELAY_KEY_WRITE
如果要延迟表的关键更新,请将其设置为1,直到表关闭。见的描述
delay_key_write在系统变量第5.1.5节,“服务器系统变量”。(MyISAM只)。
ENCRYPTION
将该ENCRYPTION选项
设置'Y'为对InnoDB在每个文件表格
空间中创建的表
启用页面级数据加密。选项值不区分大小写。该
ENCRYPTION选项与InnoDB表空间加密功能一起引入
; 请参见
第14.7.10节“InnoDB表空间加密”。该
keyring_file插件必须加载才能使用该ENCRYPTION选项。
INSERT_METHOD
如果要将数据插入MERGE
表中,则必须使用INSERT_METHOD
该行应插入的表进行指定。
INSERT_METHOD是MERGE仅用于表格的选项
。使用FIRST或的值
LAST可以使插入到第一个或最后一个表,或使用值
NO来防止插入。请参见
第15.7节“MERGE存储引擎”。
KEY_BLOCK_SIZE
对于MyISAM表格,
KEY_BLOCK_SIZE可选地指定用于索引关键字块的字节大小。该值被视为提示; 如果需要可以使用不同的尺寸。KEY_BLOCK_SIZE为单个索引定义指定的值将覆盖表级别的
KEY_BLOCK_SIZE值。
对于InnoDB表,
KEY_BLOCK_SIZE可选地指定用于压缩表的
页面大小(以千字节为单位)。该
值被视为提示; 如果需要,可以使用不同的尺寸。只能小于或等于该
值。值为0表示默认的压缩页面大小,它是该值的一半
。根据不同
,可能的
值包括0,1,2,4,8和16.有关更多信息,请参见第14.9.1节“InnoDB表压缩”。
InnoDBKEY_BLOCK_SIZEInnoDBKEY_BLOCK_SIZEinnodb_page_sizeinnodb_page_sizeinnodb_page_sizeKEY_BLOCK_SIZE
Oracle建议innodb_strict_mode在KEY_BLOCK_SIZE为
InnoDB表指定时启用
。当
innodb_strict_mode被启用,指定一个无效的
KEY_BLOCK_SIZE值返回一个错误。如果
innodb_strict_mode禁用,则无效KEY_BLOCK_SIZE值会导致警告,并且该
KEY_BLOCK_SIZE选项将被忽略。
该Create_options响应列
SHOW TABLE STATUS报告最初指定的KEY_BLOCK_SIZE选项,一样SHOW CREATE TABLE。
InnoDB仅KEY_BLOCK_SIZE在桌面级别支持
。
KEY_BLOCK_SIZE不支持32k和64k innodb_page_size
值。InnoDB表压缩不支持这些页面大小。
MAX_ROWS
您计划在表格中存储的最大行数。这不是一个硬性限制,而是存储引擎提示该表必须能够存储至少这么多行。
使用MAX_ROWS与
NDB表来控制表的分区的数目被弃用NDB簇7.5.4的。它在后来的版本中仍然支持向后兼容,但在未来的发行版中可能会被删除。改为使用PARTITION_BALANCE; 请参阅
设置NDB_TABLE选项。
该NDB存储引擎将这个值作为最大。如果您计划创建非常大的NDB簇表(包含数百万行),则应该使用此选项以确保NDB
在用于存储表主键的散列的散列表中分配足够数量的索引槽,方法
是您希望插入到表中的行数。
MAX_ROWS = 2 *
rowsrows
最大值MAX_ROWS是4294967295; 较大的值被截断到这个限制。
MIN_ROWS
您计划在表中存储的最小行数。该
MEMORY存储引擎使用此选项,因为一个关于内存使用提示。
PACK_KEYS
仅适用于MyISAM表格。如果您想拥有较小的索引,请将此选项设置为1。这通常会使更新速度变慢,读取速度更快 将该选项设置为0将禁用所有键的打包。将其设置为
DEFAULT告诉存储引擎只封装长CHAR,
VARCHAR,
BINARY,或
VARBINARY列。
如果你不使用PACK_KEYS,默认是打包字符串,但不是数字。如果你使用
PACK_KEYS=1,号码也是打包的。
打包二进制数字键时,MySQL使用前缀压缩:
每个密钥需要一个额外的字节来指示前一个密钥的多少个字节对于下一个密钥是相同的。
指向行的指针直接以高字节顺序存储,以提高压缩率。
这意味着如果在两个连续的行上有许多相等的密钥,所有跟随的“ 相同 ”密钥通常只需要两个字节(包括指向该行的指针)。将其与以下键所需的普通情况
storage_size_for_key + pointer_size(其中指针大小通常为4)进行比较。相反,只有在有许多相同的数字时,才能从前缀压缩中获益。如果所有密钥都完全不同,那么如果密钥不是可以具有NULL值的密钥,则每个密钥使用多一个字节。(在这种情况下,打包的密钥长度存储在用于标记密钥是否相同的字节中NULL。)
PASSWORD
此选项未使用。如果您需要打乱
.frm文件并使其不能用于任何其他MySQL服务器,请联系我们的销售部门。
ROW_FORMAT
定义存储行的物理格式。
在执行禁用严格模式的CREATE TABLE
语句时,如果您指定用于表的存储引擎不支持的行格式,则使用该存储引擎的默认行格式创建表。列中响应
的信息
是实际使用的行格式。这可能与列中的值不同,
因为原始
定义在创建期间保留。还会报告原始
语句中使用的行格式。
Row_formatSHOW TABLE STATUSCreate_optionsCREATE TABLESHOW CREATE
TABLECREATE TABLE
行格式选择根据用于表格的存储引擎而有所不同。
对于InnoDB表格:
默认行格式由innodb_default_row_format默认设置为,定义
DYNAMIC。ROW_FORMAT选项未定义或使用时使用默认行格式
ROW_FORMAT=DEFAULT。
如果ROW_FORMAT未定义该选项,或者如果ROW_FORMAT=DEFAULT使用该选项,则重建表的操作也将以静默方式将表格的行格式更改为默认定义的表格格式
innodb_default_row_format。有关更多信息,请参见
第14.11.2节“指定表格的行格式”。
为了更有效地InnoDB存储数据类型,尤其是BLOB
类型,请使用DYNAMIC。有关与行格式相关的要求
,请参见
第14.11.3节“动态和压缩行格式”DYNAMIC。
要为InnoDB
表启用压缩,请指定ROW_FORMAT=COMPRESSED。有关与行格式相关的要求,请参见第14.9节“InnoDB表和页面压缩”COMPRESSED。
通过指定REDUNDANT行格式,仍然可以请求旧版本MySQL中使用的
行格式。
当您指定非默认
ROW_FORMAT子句时,请考虑启用
innodb_strict_mode
配置选项。
ROW_FORMAT=FIXED不受支持。如果
ROW_FORMAT=FIXED在innodb_strict_mode禁用时指定,
则InnoDB发出警告并假定ROW_FORMAT=DYNAMIC。如果
ROW_FORMAT=FIXED在innodb_strict_mode启用时指定
,默认情况下InnoDB
返回错误。
有关InnoDB
行格式的更多信息,请参见第14.11节“InnoDB行存储和行格式”。
对于MyISAM表格,选项值可以是
FIXED或DYNAMIC用于静态或可变长度的行格式。
myisampack将类型设置为
COMPRESSED。请参见
第15.2.3节“MyISAM表格存储格式”。
对于NDB表,ROW_FORMATMySQL NDB Cluster 7.5.1和更高版本中的默认值
是DYNAMIC。(以前,它是
FIXED。)
STATS_AUTO_RECALC
指定是否自动重新计算
持续的统计数据为InnoDB表。该值DEFAULT导致表的持久统计信息设置由innodb_stats_auto_recalc
配置选项确定
。该值1导致统计信息在表中数据的10%已更改时重新计算。该值0可防止对此表进行自动重新计算; 在此设置下,ANALYZE TABLE
在对表格进行重大更改后,发布重新计算统计数据的声明。有关持久统计信息功能的更多信息,请参阅
第14.6.12.1节“配置持久优化器统计参数”。
STATS_PERSISTENT
指定是否启用
持续统计为一个InnoDB表。该值DEFAULT导致表的持久统计信息设置由innodb_stats_persistent
配置选项确定
。该值为1表启用持久性统计信息,而值
0会关闭此功能。在通过a CREATE
TABLE或ALTER TABLE语句启用持久性统计ANALYZE TABLE
信息后,在将代表性数据加载到表中之后,发出语句来计算统计信息。有关持久统计信息功能的更多信息,请参阅
第14.6.12.1节“配置持久优化器统计参数”。
STATS_SAMPLE_PAGES
估计索引列的基数和其他统计数据时要抽样的索引页数,例如由ANALYZE
TABLE。有关更多信息,请参见
第14.6.12.1节“配置持久优化器统计参数”。
TABLESPACE
该TABLESPACE选项用于在InnoDB常规表空间中创建表。
CREATE TABLEtbl_name... TABLESPACE [=]tablespace_name
您指定的一般表空间必须在使用该TABLESPACE选项之前存在。有关常规表空间的信息,请参见
第14.7.9节“InnoDB常规表空间”。
这
是一个区分大小写的标识符。它可能被引用或不引用。正斜杠字符(“ / ”)是不允许的。以“ innodb_ ”开头的名称保留作特殊用途。
tablespace_name
该TABLESPACE选项可用于将InnoDB表分区或子分区分配给
常规表空间,单独的每个表文件表空间或系统表空间。TABLESPACEMySQL 5.7中添加了对表分区和子分区的选项支持。所有分区必须属于同一个存储引擎。
在表级别指定的表空间成为新分区和子分区的默认表空间。通过在a CREATE TABLE或
ALTER TABLE语句中的分区或子分区级别指定表空间,可以覆盖默认表空间
。以下示例显示了在表级别和分区级别定义的表空间。
mysql> CREATE TABLE t1(一个INT NOT NULL,PRIMARY KEY(a))
- > ENGINE = InnoDB TABLESPACE ts1
- >按范围划分(a)分区3(
- >分区P1值小于(2),
- >分区P2值小于(4)TABLESPACE ts2,
- >分区P3值小于(6)TABLESPACE ts3);
有关TABLESPACE
选项和分区的更多信息,请参见
第14.7.9节“InnoDB常规表空间”
要在系统表空间中创建表,请指定
innodb_system为表空间名称。
CREATE TABLE tbl_name... TABLESPACE [=] innodb_system
使用该TABLESPACE [=] innodb_system
选项,可以将任何未压缩行格式的表放入系统表空间中,而不管innodb_file_per_table
设置如何
。例如,您可以ROW_FORMAT=DYNAMIC使用该TABLESPACE [=] innodb_system
选项向系统表空间添加一个表
。
要在每个文件表的表空间中创建表,请指定
innodb_file_per_table为表空间名称。
CREATE TABLE tbl_name... TABLESPACE [=] innodb_file_per_table
如果innodb_file_per_table启用,则不需要指定
TABLESPACE=innodb_file_per_table创建每个InnoDB文件表的表空间。启用InnoDB时,默认情况下,表格是在每个文件表格空间中创建的
innodb_file_per_table。
该DATA DIRECTORY条款是允许的,
CREATE TABLE ...
TABLESPACE=innodb_file_per_table但不支持与该TABLESPACE选项结合使用
。
该TABLESPACE选项支持with
ALTER TABLE和
ALTER TABLE ...
REORGANIZE PARTITION语句,它们可以分别用于将表和分区从一个表空间移动到另一个表空间。有关更多信息,请参见
第14.7.9节“InnoDB常规表空间”。
该STORAGE表选项仅采用了与NDB表。
STORAGE确定用于存储的类型(磁盘或存储器),并且可以是一个DISK,
MEMORY或DEFAULT。
TABLESPACE ... STORAGE DISK将表分配给NDB群集磁盘数据表空间。表空间必须已经使用创建CREATE
TABLESPACE。有关更多信息,请参见
第21.5.13节“NDB群集磁盘数据表”。
一个STORAGE子句不能被用在
CREATE TABLE声明中没有TABLESPACE从句。
用于访问一组相同的
MyISAM表格。这只适用于
MERGE表格。请参见
第15.7节“MERGE存储引擎”。
您必须具有SELECT,
UPDATE和
DELETE您映射到MERGE表格的表的特权。
以前,所用的所有表必须与MERGE表本身位于同一个数据库中。此限制不再适用。
partition_options可用于控制使用创建的表的分区
CREATE TABLE。
并非partition_options本节开始语法中显示的所有选项
都适用于所有分区类型。请参阅以下各种类型的列表,以获取每种类型的特定信息,并参见第22章分区,以获取有关MySQL中的分区的工作原理和用法的更多完整信息,以及表格创建和其他相关语句的其他示例到MySQL分区。
分区可以被修改,合并,添加到表中,并从表中删除。有关完成这些任务的MySQL语句的基本信息,请参见第13.1.8节“ALTER TABLE语法”。有关更详细的说明和示例,请参见 第22.3节“分区管理”。
PARTITION BY
如果使用,一个partition_options条款开始PARTITION BY。该子句包含用于确定分区的函数; 该函数返回范围从1到的整数值
num,其中
num是分区数量。(表中可能包含的用户定义分区的最大数量为1024;本节后面讨论的子分区数量包含在此最大值中。)
子句中expr使用
的表达式()
PARTITION BY不能引用不在正在创建的表中的任何列; 这种引用是特别不允许的,并导致语句失败并出现错误。(错误#29444)
HASH(
expr)
散列一列或多列以创建放置和定位行的键。expr是使用一个或多个表格列的表达式。这可以是产生单个整数值的任何有效的MySQL表达式(包括MySQL函数)。例如,这些都是有效的
CREATE TABLE陈述,使用
PARTITION BY HASH:
CREATE TABLE t1(col1 INT,col2 CHAR(5))
PARTITION BY HASH(col1);
CREATE TABLE t1(col1 INT,col2 CHAR(5),col3 DATETIME)
HASH分区(年份(col3));
你不能使用任何一个VALUES LESS THAN或者
VALUES IN子句PARTITION
BY HASH。
PARTITION BY HASH使用余数
expr除以分区数(即模数)。有关示例和其他信息,请参见第22.2.4节“HASH分区”。
的LINEAR关键字需要稍微不同的算法。在这种情况下,作为一个或多个逻辑AND运算的结果,计算存储行的分区的编号。有关线性散列的讨论和示例,请参见第22.2.4.1节“LINEAR散列
分区”。
KEY(
column_list)
这与HASHMySQL 相似,除了提供哈希函数以保证数据的均匀分布。的column_list
参数是简单的1个或多个表列(最大:16)的列表。这个例子显示了一个按键分区的简单表格,其中有4个分区:
CREATE TABLE tk(col1 INT,col2 CHAR(5),col3 DATE)
PARTITION BY KEY(col3)
分区4;
对于按键分区的表,可以使用LINEAR关键字进行线性分区。这与被分区的表具有相同的效果HASH。也就是说,分区号是使用
&
运算符而不是模数(有关详细信息,请参见
第22.2.4.1节“LINEAR HASH分区”和
第22.2.5节“KEY分区”)。此示例使用按键进行线性分区以在5个分区之间分配数据:
CREATE TABLE tk(col1 INT,col2 CHAR(5),col3 DATE)
线性密钥分区(col3)
分区5;
该ALGORITHM={1|2}选项受支持[SUB]PARTITION BY [LINEAR] KEY。
ALGORITHM=1导致服务器使用与MySQL 5.1相同的密钥散列函数;
ALGORITHM=2意味着服务器KEY在MySQL 5.5和更高版本中使用默认实现和使用的新分区表的键哈希函数。(使用MySQL 5.5及更高版本中使用的密钥散列函数创建的分区表不能用于MySQL 5.1服务器。)不指定该选项与使用该选项具有相同的效果ALGORITHM=2。此选项主要用于[LINEAR] KEY在MySQL 5.1和更高版本的MySQL版本之间升级或降级
分区表,或用于创建分区表KEY或者LINEAR
KEY在可以在MySQL 5.1服务器上使用的MySQL 5.5或更高版本的服务器上。有关更多信息,请参见
第13.1.8.1节“ALTER TABLE分区操作”。
MySQL 5.7(及更高版本)中的 mysqldump将这个选项写入版本化注释中,如下所示:
CREATE TABLE t1(一个INT)
/ *!50100 PARTITION BY KEY * / / *!50611 ALGORITHM = 1 * / / *!50100()
分区3 * /
这会导致MySQL 5.6.10和更早版本的服务器忽略该选项,否则会在这些版本中导致语法错误。如果您计划加载在MySQL 5.7服务器上创建的转储,然后再使用分区或子分区的表格将其转储KEY到版本5.6.11之前的MySQL 5.6服务器,请务必查阅
影响升级到MySQL 5.6的更改。(如果您正在将包含KEY
由MySQL 5.7实际上5.6.11或更高版本的服务器创建的分区或子分区表的转储加载到MySQL 5.5.30或更早版本的服务器中,那么此处找到的信息也适用。
同样在MySQL 5.6.11和更高版本中,ALGORITHM=1
在SHOW CREATE TABLE使用版本化注释的输出中以必要
的方式显示,与mysqldump相同
。
即使在创建原始表时指定了此选项,它也ALGORITHM=2
始终从SHOW CREATE TABLE输出中省略。
你不能使用任何一个VALUES LESS THAN或者
VALUES IN子句PARTITION
BY KEY。
RANGE(
expr)
在这种情况下,expr使用一组VALUES LESS THAN
运算符显示一系列值。使用范围分区时,必须使用至少一个分区VALUES LESS THAN。您不能使用VALUES IN范围分区。
对于分区为的表RANGE,
VALUES LESS THAN必须与整数字面值或用于计算单个整数值的表达式一起使用。在MySQL 5.7中,您可以在使用定义的表中克服此限制
PARTITION BY RANGE COLUMNS,如本节后面所述。
根据以下方案,假设您有一张表,您希望在包含年份值的列上进行分区。
| 分区号码: | 年范围: |
|---|---|
| 0 | 1990年及以前 |
| 1 | 1991年至1994年 |
| 2 | 1995年至1998年 |
| 3 | 1999年至2002年 |
| 4 | 2003年至2005年 |
| 五 | 2006年及以后 |
实现这种分区方案的表可以通过CREATE TABLE
此处显示的语句来实现:
CREATE TABLE t1(
year_col INT,
some_data INT
)
按范围划分(year_col)(
PARTITION p0值小于(1991),
PARTITION p1值小于(1995),
分区p2小于(1999),
分区p3值小于(2002),
分区p4值小于(2006),
PARTITION p5的值小于MAXVALUE
);
PARTITION ... VALUES LESS THAN ...
声明以连续方式工作。VALUES LESS
THAN MAXVALUE用于指定
大于最大值的“ 剩余 ”值。
VALUES LESS THAN子句按照与块的case
部分类似的方式switch ... case(如许多编程语言中发现的那样,如C,Java和PHP)顺序工作。也就是说,子句的排列方式必须使每个连续的上限VALUES LESS
THAN大于前一个的上限,并且引用的MAXVALUE最后一个是列表中的最后一个。
RANGE
COLUMNS(
column_list)
此变体RANGE有助于使用多列上的范围条件对查询进行分区修剪(即,具有诸如WHERE a = 1 AND b
< 10或的条件WHERE a = 1 AND b = 10 AND c
< 10)。它使您能够使用COLUMNS子句中的列列表和每个分区定义子句中的一组列值指定多列中的值范围
。(在最简单的情况下,该集合由单个列组成。)可以在and中
引用的最大列数是16。
PARTITION ... VALUES LESS THAN
(value_list)column_listvalue_list
该column_list中使用的
COLUMNS条款可能只包含列的名称; 列表中的每列必须是以下MySQL数据类型之一:整数类型; 字符串类型; 和时间或日期列类型。使用列
BLOB,TEXT,
SET,ENUM,
BIT,或空间数据类型不允许; 使用浮点数类型的列也是不允许的。您也可以不在该COLUMNS
子句中使用函数或算术表达式。
VALUES LESS THAN在分区定义中使用
的子句必须为COLUMNS()
子句中出现的每一列指定一个立即数值; 也就是说,用于每个VALUES LESS THAN子句的值列表
必须包含与COLUMNS子句中列出的列相同数量的值
。尝试到在使用更多或更少的值VALUES LESS THAN以外还有的条款COLUMNS条款会导致失败,错误的语句在列列表的使用不一致的分区...。你不能使用NULL任何值出现在
VALUES LESS THAN。可以使用
MAXVALUE 对于除第一列以外的给定列,不止一次,如以下示例所示:
CREATE TABLE rc(
INT NOT NULL,
b INT NOT NULL
)
按范围分列(a,b)(
PARTITION p0的值小于(10,5),
PARTITION p1的值小于(20,10),
PARTITION p2的值小于(50,MAXVALUE),
分区p3值小于(65,MAXVALUE),
PARTITION p4的值小于(MAXVALUE,MAXVALUE)
);
VALUES LESS THAN值列表中
使用的每个值必须完全匹配相应列的类型; 没有转换。例如,不能将字符串
'1'用作与使用整数类型的列相匹配的值(您必须使用数字
1),也不能使用数字
1作为与使用字符串类型的列匹配的值(例如,一个案例,你必须使用一个引用的字符串:)'1'。
有关更多信息,请参见 第22.2.1节“RANGE分区”和 第22.4节“分区修剪”。
LIST(
expr)
当根据表格列分配具有一组可能值(如状态或国家/地区代码)的分区时,此功能很有用。在这种情况下,属于某个州或国家的所有行都可以分配给一个分区,或者可以为某些州或国家的某个分区保留一个分区。它类似于
RANGE,除了仅VALUES
IN用于指定每个分区的允许值之外。
VALUES IN与要匹配的值列表一起使用。例如,您可以创建一个分区方案,如下所示:
CREATE TABLE client_firms(
id INT,
名称VARCHAR(35)
)
PARTITION BY LIST(id)(
PARTITION r0(1,5,9,13,17,21),
(2,6,10,14,18,22)中的PARTITION r1值
(3,7,11,15,19,23)中的分区r2值
(4,8,12,16,20,24)中的分区r3值
);
使用列表分区时,您必须使用至少一个分区VALUES IN。您不能使用
VALUES LESS THAN与PARTITION BY
LIST。
对于分区表LIST,与VALUES IN必须一起使用的值列表必须仅包含整数值。在MySQL 5.7中,您可以使用LIST
COLUMNS本节后面介绍的partitioning by来克服此限制。
LIST
COLUMNS(
column_list)
此变体LIST有助于使用多列上的比较条件对查询进行分区修剪(即,具有诸如WHERE a =
5 AND b = 5或的条件WHERE a = 1 AND b = 10 AND c
= 5)。它使您能够使用COLUMNS子句中的列列表和每个分区定义子句中的一组列值指定多个列中的
值。
PARTITION ... VALUES IN
(value_list)
管理有关数据类型中使用的列列表中的规则和使用值列表是相同的那些在使用的列清单,并在使用值列表分别,只是在
条款,是不允许的,和你可能会使用。
LIST
COLUMNS(column_list)VALUES
IN(value_list)RANGE
COLUMNS(column_list)VALUES LESS
THAN(value_list)VALUES INMAXVALUENULL
有用于值列表之间的一个重要区别VALUES IN有PARTITION
BY LIST COLUMNS,而不是当它与使用
PARTITION BY LIST。使用时
PARTITION BY LIST COLUMNS,VALUES IN子句中的每个元素必须是一
组列值; 每个集合中的值的数量必须与该COLUMNS子句中使用的列的数量相同,并且这些值的数据类型必须与列的数据类型匹配(并以相同的顺序出现)。在最简单的情况下,该集合由单个列组成。column_list
在构成元素和元素中
可以使用的最大列数value_list是16。
由以下CREATE
TABLE语句定义的表提供了使用LIST COLUMNS分区的表的示例
:
CREATE TABLE lc(
一个INT NULL,
b INT NULL
)
列表分区列表(a,b)(
((0,0),(NULL,NULL))中的PARTITION p0值
((0,1),(0,2),(0,3),(1,1),(1,2))中的分区p1值,
((1,0),(2,0),(2,1),(3,0),(3,1))中的分区p2值,
((1,3),(2,2),(2,3),(3,2),(3,3))中的分区p3值
);
PARTITIONS
num
分区的数量可以有选择地用一个
子句来指定
,其中是分区的数量。如果使用此子句和任何
子句,则
必须等于使用子句声明的任何分区的总数
。
PARTITIONS numnumPARTITIONnumPARTITION
无论您是否PARTITIONS
在创建由RANGEor 分区的表中使用子句
LIST,都必须PARTITION
VALUES在表定义中至少包含一个子句(请参见下文)。
SUBPARTITION BY
分区可以可选地分成多个子分区。这可以通过使用可选的SUBPARTITION BY子句来指示
。子分区可以通过HASH或完成KEY。这些都可能是LINEAR。这些工作方式与之前对等效分区类型所描述的相同。(不可能通过LIST或进行子分区
RANGE。)
可以使用SUBPARTITIONS关键字后跟一个整数值来指示子分区的数量
。
严格检查PARTITIONS或使用
SUBPARTITIONS条款中使用的值,
并且该值必须遵守以下规则:
该值必须是正整数,非零整数。
不允许前导零。
该值必须是整数字面值,不能是表达式。例如,PARTITIONS
0.2E+01即使0.2E+01评估结果
也是不允许的
2。(Bug#15890)
partition_definition
每个分区可以使用一个partition_definition子句单独定义
。构成本条款的各个部分如下:
PARTITION
partition_name
指定分区的逻辑名称。
VALUES
对于范围分区,每个分区必须包含一个
VALUES LESS THAN子句; 对于列表分区,您必须VALUES
IN为每个分区指定一个子句。这用于确定哪些行将存储在此分区中。见分区类型的讨论
第22章,分区,语法的例子。
[STORAGE] ENGINE
分区处理程序接受[STORAGE]
ENGINE两者PARTITION和
的选项
SUBPARTITION。目前,可以使用这种方法的唯一方法是将所有分区或所有子分区设置为同一个存储引擎,并且尝试为同一表中的分区或子分区设置不同的存储引擎将导致错误ERROR 1469( HY000):在这个版本的MySQL中,分区中的处理程序组合是不允许的。我们希望在未来的MySQL版本中解除对分区的限制。
COMMENT
可选COMMENT子句可用于指定描述分区的字符串。例:
评论='1999年前的数据'
分区注释的最大长度是1024个字符。
DATA DIRECTORY 和 INDEX
DIRECTORY
DATA DIRECTORY并且INDEX
DIRECTORY可以用来指示分别存储该分区的数据和索引的目录。无论是
和
data_dir
必须是绝对系统路径名。
index_dir
从MySQL 5.7.17开始,您必须有权
FILE使用
DATA DIRECTORY或INDEX
DIRECTORY分区选项。
例:
CREATE TABLE th(id INT,name VARCHAR(30),adate DATE)
按列表划分(年份(adate))
(
PARTITION p1999 VALUE IN(1995,1999,2003)
DATA DIRECTORY =' /var/appdata/95/data'
INDEX DIRECTORY =' /var/appdata/95/idx',
分区p2000值(1996年,2000年,2004年)
DATA DIRECTORY =' /var/appdata/96/data'
INDEX DIRECTORY =' /var/appdata/96/idx',
(1997年,2001年,2005年)PARTITION p2001数值
DATA DIRECTORY =' /var/appdata/97/data'
INDEX DIRECTORY =' /var/appdata/97/idx',
(1998年,2002年,2006年)的p2002值
DATA DIRECTORY =' /var/appdata/98/data'
INDEX DIRECTORY =' /var/appdata/98/idx'
);
DATA DIRECTORY并且其INDEX
DIRECTORY行为与用于表的CREATE TABLE语句
table_option子句
中的行为相同
MyISAM。
每个分区可以指定一个数据目录和一个索引目录。如果未指定,数据和索引默认存储在表的数据库目录中。
在Windows上,单个分区或表的子分区不支持DATA DIRECTORY和
INDEX DIRECTORY选项MyISAM,并且该表单的各个分区或子分区
INDEX DIRECTORY不支持该
选项
InnoDB。这些选项在Windows上被忽略,除了生成警告。(错误#30459)
如果有效DATA DIRECTORY,INDEX
DIRECTORY则创建分区表时将忽略和选项
NO_DIR_IN_CREATE。(Bug#24633)
MAX_ROWS 和
MIN_ROWS
可用于分别指定要存储在分区中的最大和最小行数。值max_number_of_rows
和min_number_of_rows必须是正整数。与具有相同名称的表级选项一样,这些选项仅作为
对服务器的“ 建议 ”,并不是硬性限制。
TABLESPACE
可用于将InnoDB表分区或子分区
分配给常规表空间,单独的每个表文件表空间或系统表空间。TABLESPACE
MySQL 5.7中添加了对表分区和子分区的选项支持,请参见
第14.7.9节“InnoDB常规表空间”。它也受到NDB集群的支持。所有分区必须属于同一个存储引擎。
subpartition_definition
分区定义可以选择性地包含一个或多个
subpartition_definition子句。每个这些由在最小的
,其中
是用于所述子分区的标识符。除了替换
关键字之外
,子分区定义的语法与分区定义的语法相同。
SUBPARTITION
namenamePARTITIONSUBPARTITION
子分区必须完成HASH或
KEY,并且只能在完成
RANGE或LIST
分区。参见第22.2.6节“子分区”。
按生成的列进行分区
通过生成的列进行分区是允许的。例如:
CREATE TABLE t1( s1 INT, s2 INT AS(EXP(s1))存储 ) 按列表划分(s2)( PARTITION p1值(1) );
分区会将生成的列视为常规列,从而实现对不允许进行分区的功能的限制的解决方法(请参见
第22.6.3节“与功能相关的分区限制”)。上例演示了这种技术:
EXP()不能直接在PARTITION BY子句中使用,但EXP()允许使用定义的生成列。
原始CREATE TABLE
语句,包括所有规范和表格选项,在创建表格时由MySQL存储。信息将保留,以便如果使用ALTER
TABLE语句更改存储引擎,归类或其他设置,则保留指定的原始表格选项。这使您即使在两种引擎支持的行格式不同的情况下也可以在表格类型InnoDB和
MyISAM表格类型之间进行切换
。
由于原始语句的文本被保留,但由于某些值和选项可能会被默认重新配置(例如ROW_FORMAT),所以活动表定义(可通过DESCRIBE或
可以访问
SHOW TABLE STATUS)和表创建字符串(可通过SHOW
CREATE TABLE)将会保留报告不同的值。
MySQL通过.frm
数据库目录中的表格格式(定义)文件来表示每个表格。表的存储引擎也可能创建其他文件。
对于以InnoDB文件为单位的表空间或常规表空间创建的表,表数据和关联索引存储在数据库目录中的
ibd文件中。当InnoDB在系统表空间中创建表,表数据和索引存储在
ibdata *文件表示系统表空间。该
innodb_file_per_table选项控制是否默认情况下在每个文件表空间或系统表空间中创建表。TABLESPACE无论innodb_file_per_table设置如何,该
选项都可用于将表放置在每个文件表空间,常规表空间或系统表空间中
。
对于MyISAM表格,存储引擎会创建数据和索引文件。因此,对于每个MyISAM
表tbl_name,有三个磁盘文件。
| 文件 | 目的 |
|---|---|
|
表格格式(定义)文件 |
|
数据文件 |
|
索引文件 |
第15章“ 备用存储引擎 ”介绍了每个存储引擎为表示表而创建的文件。如果表名包含特殊字符,则表格文件的名称包含这些字符的编码版本,如 第9.2.3节“将标识符映射到文件名”中所述。
TEMPORARY创建表格时
可以使用关键字。一个TEMPORARY表只在当前会话中可见,而当会话关闭时自动删除。这意味着两个不同的会话可以使用相同的临时表名称而不会相互冲突,也不会使用同名的现有非TEMPORARY表。(在删除临时表之前隐藏现有表。)
CREATE TABLE会导致隐式提交,除非与TEMPORARY
关键字一起使用。请参见第13.3.3节“导致隐式提交的语句”。
TEMPORARY表与数据库(模式)有非常松散的关系。删除数据库不会自动删除TEMPORARY在该数据库中创建的任何表。另外,TEMPORARY如果您在CREATE TABLE语句中使用数据库名称限定表名,则可以在不存在的数据库中创建
表
。在这种情况下,对表的所有后续引用都必须使用数据库名称进行限定。
要创建临时表,您必须拥有该
CREATE TEMPORARY TABLES
权限。会话创建临时表后,服务器不会在该表上执行进一步的特权检查。所述创建会话可以在桌子上进行任何操作,例如
DROP TABLE,
INSERT,
UPDATE,或
SELECT。
这种行为的一个含义是即使当前用户没有权限创建它们,会话也可以操纵它的临时表。假设当前用户没有CREATE TEMPORARY TABLES
权限但能够执行一个定义者上下文存储过程,该存储过程使用拥有CREATE TEMPORARY TABLES并创建临时表的用户的特权执行。在执行过程时,会话将使用定义用户的权限。过程返回后,有效权限将恢复为当前用户的权限,该用户仍可以看到临时表并对其执行任何操作。
用于CREATE TABLE ... LIKE根据另一个表的定义(包括原始表中定义的所有列属性和索引)创建一个空表:
CREATE TABLEnew_tblLIKEorig_tbl;
该副本是使用与原始表格相同版本的表格存储格式创建的。该
SELECT权限需要对原始表。
LIKE 仅适用于基表,不适用于视图。
你不能执行CREATE TABLE或
CREATE TABLE ... LIKE同时
LOCK TABLES声明生效。
CREATE TABLE ...
LIKE进行相同的检查,
CREATE TABLE而不仅仅是复制.frm文件。这意味着如果当前的SQL模式与创建原始表时有效的模式不同,则对于新模式,表定义可能被认为是无效的,并且语句将失败。
对于CREATE TABLE ... LIKE,目标表保留从原始表生成的列信息。
CREATE TABLE ... LIKE不保留为原始表或任何外键定义指定的任何
DATA DIRECTORY或INDEX
DIRECTORY表选项。
如果原始表格是TEMPORARY表格,
CREATE TABLE ... LIKE则不保留
TEMPORARY。要创建
TEMPORARY目的地表格,请使用
CREATE TEMPORARY TABLE ... LIKE。
您可以通过在SELECT语句末尾添加语句来创建另一个表格
CREATE TABLE:
CREATE TABLEnew_tbl[AS] SELECT * FROMorig_tbl;
MySQL为所有元素创建新的列
SELECT。例如:
mysql>CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,- >PRIMARY KEY (a), KEY(b))- >ENGINE=MyISAM SELECT b,c FROM test2;
这将创建一个MyISAM表有三列,a,b,和
c。该ENGINE选项是CREATE TABLE
声明的一部分,不应在以下情况下使用
SELECT; 这会导致语法错误。对于其他CREATE TABLE选项
也是如此
CHARSET。
请注意,SELECT语句中的列
将附加到表格的右侧,而不会与其重叠。以下面的例子:
MySQL的>SELECT * FROM foo;+ --- + | n | + --- + | 1 | + --- + MySQL的>CREATE TABLE bar (m INT) SELECT n FROM foo;查询OK,1行受影响(0.02秒) 记录:1重复:0警告:0 MySQL的>SELECT * FROM bar;+ ------ + --- + | m | n | + ------ + --- + | NULL | 1 | + ------ + --- + 一排(0.00秒)
对于表中的每一行foo,将插入一行,bar其中foo包含新列的值
和默认值。
在由此产生的表中
CREATE TABLE ...
SELECT,仅在该CREATE TABLE部分中命名的列
首先出现。在这两个部分命名的列或仅在SELECT部分命名的列
。SELECT列的数据类型也可以通过指定CREATE TABLE零件中的列来覆盖
。
如果在将数据复制到表格时发生任何错误,它会自动删除并且不会创建。
您可以先于SELECT通过
IGNORE或REPLACE指示如何处理重复的唯一键值的行。使用时IGNORE,丢弃在唯一键值上复制现有行的行。用
REPLACE新行替换具有相同唯一键值的行。如果既没有IGNORE也没有
REPLACE被指定,重复的唯一键值导致错误。有关更多信息,请参阅
IGNORE关键字和严格SQL模式的比较。
因为基础SELECT语句中行的排序
不总是可以确定的,CREATE TABLE ... IGNORE SELECT
并且CREATE TABLE ... REPLACE SELECT
语句被标记为基于语句的复制不安全。这些语句在使用基于语句的模式时会在错误日志中产生警告,并在使用MIXED模式时使用基于行的格式写入二进制日志
。另请参见
第16.2.1.1节“基于声明和基于行的复制的优点和缺点”。
CREATE TABLE ...
SELECT不会自动为您创建任何索引。这是故意做出的,尽可能灵活。如果你想在创建的表中有索引,你应该在SELECT语句之前指定它们
:
MySQL的> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
因为CREATE TABLE ... SELECT目标表不保存关于选定表格中的列是否为生成列的信息。该SELECT语句的
一部分不能将值分配给目标表中的生成列。
数据类型可能会发生一些转换。例如,该
AUTO_INCREMENT属性不会保留,并且VARCHAR列可以成为
CHAR列。再培训属性是NULL(或NOT
NULL),对于有他们这些列,
CHARACTER SET,COLLATION,
COMMENT,和DEFAULT
条款。
在创建表格时
CREATE
TABLE ... SELECT,请确保在查询中别名任何函数调用或表达式。如果您不这样做,则该
CREATE语句可能会失败或导致不需要的列名称。
CREATE TABLE artists_and_works SELECT artist.name,COUNT(work.artist_id)AS number_of_works FROM artist LEFT JOIN work on artist.id = work.artist_id GROUP BY artist.id;
您还可以在创建的表中明确指定列的数据类型:
CREATE TABLE foo(TINYINT NOT NULL)SELECT b + 1作为FROM栏;
因为CREATE TABLE
... SELECT,如果IF NOT EXISTS给出并且目标表存在,则不会将任何内容插入到目标表中,并且不会记录该语句。
为确保二进制日志可用于重新创建原始表,MySQL不允许在执行期间同时插入
CREATE TABLE ...
SELECT。
您不能在以下语句中
使用FOR UPDATE它们的一部分
。如果您尝试这样做,则说明失败。
SELECTCREATE
TABLE new_table SELECT ... FROM
old_table ...
MySQL支持外键,它允许您在表中交叉引用相关数据,并支持
外键约束,这有助于保持这种扩展数据的一致性。在CREATE TABLEor
ALTER TABLE语句中外键约束定义的基本语法如下所示:
[CONSTRAINT [symbol]] FOREIGN KEY [index_name](index_col_name,...) 参考文献tbl_name(index_col_name,...) [在删除reference_option] [在更新reference_option]reference_option: RESTRICT | CASCADE | SET NULL | NO ACTION | 默认设置
index_name代表外键ID。index_name如果在可支持外键的子表上已经有显式定义的索引,则该值将被忽略。否则,MySQL会隐式创建一个按照以下规则命名的外键索引:
如果已定义,CONSTRAINT
symbol则使用该值。否则,使用该FOREIGN KEY
index_name值。
如果既没有CONSTRAINT
symbol或FOREIGN
KEY index_name定义,使用引用外键列的名称所产生的外键索引名。
外键定义受以下条件限制:
外键关系涉及一个包含中心数据值的
父表以及一个具有相同值的子表,并
指向其父项。该
FOREIGN KEY子句在子表中指定。父表和子表必须使用相同的存储引擎。他们不能是
TEMPORARY桌子。
在MySQL 5.7中,创建外键约束需要REFERENCES父表的
特权。
外键和引用键中的相应列必须具有相似的数据类型。整数类型的大小和符号必须相同。字符串类型的长度不需要相同。对于非二进制(字符)字符串列,字符集和归类必须相同。
何时启用foreign_key_checks(默认设置)时,不允许在包含外键约束中使用的字符串列的表上使用字符集转换。解决方法在
第13.1.8节“ALTER TABLE语法”中介绍。
MySQL需要外键和引用键上的索引,以便外键检查可以很快并且不需要表扫描。在引用表中,必须有一个索引,其中外键列按照相同顺序列为
第一列。如果索引表不存在,则会在引用表上自动创建这样的索引。如果您创建另一个可用于强制执行外键约束的索引,则此索引可能会在稍后悄悄丢弃。
index_name如果给出,如前所述使用。
InnoDB允许外键引用任何列或一组列。但是,在被引用的表中,必须有一个索引,其中被引用的列按照相同顺序列为第一列。
NDB 需要在被引用为外键的任何列上显式唯一键(或主键)。
外键列上的索引前缀不受支持。这样做的一个后果是,
BLOB和
TEXT列不能被包括在一个外键,因为对这些列的索引必须总是包含一个前缀长度。
如果给出该子句,则该值(如果使用)在数据库中必须是唯一的。重复
将导致类似于以下错误:错误1022(2300):无法写入; 在表'#sql- 464_1'中复制密钥。如果没有给出该子句,或者
在
关键字之后没有包含a,则会自动创建约束的名称。
CONSTRAINT
symbolsymbolsymbolsymbolCONSTRAINT
InnoDB目前不支持具有用户定义分区的表的外键。这包括父表和子表。
此限制不适用于
NDB由KEYor 分区的表LINEAR KEY
(由NDB存储引擎支持的唯一用户分区类型
); 这些可能有外键引用或成为这些引用的目标。
对于NDB表,ON
UPDATE CASCADE在引用父表的主键时不受支持。
本节介绍外键如何帮助保证 参照完整性。
对于支持外键的存储引擎,如果父表中没有匹配的候选键值,MySQL将拒绝任何
尝试INSERT或
UPDATE尝试在子表中创建外键值的操作。
当UPDATE或
DELETE操作影响父表中具有匹配行表的父表中的键值时,结果取决于使用子句
和子
条指定的引用操作。MySQL支持五个关于要采取的操作的选项,这里列出:
ON UPDATEON DELETEFOREIGN KEY
CASCADE:从父表中删除或更新行,并自动删除或更新子表中的匹配行。这两个ON DELETE
CASCADE和ON UPDATE CASCADE
支持。在两个表之间,不要定义ON UPDATE CASCADE对父表或子表中的同一列起作用的几个
子句。
级联外键操作不会激活触发器。
SET NULL:从父表中删除或更新行,并将子表中的外键列设置为NULL。两者
ON DELETE SET NULL和ON UPDATE
SET NULL子句都受支持。
如果您指定了一个SET NULL操作,请
确保您没有将子表中的列声明为NOT
NULL。
RESTRICT:拒绝父表的删除或更新操作。指定
RESTRICT(或NO
ACTION)与省略ON
DELETEor ON UPDATE子句相同。
NO ACTION:来自标准SQL的关键字。在MySQL中,相当于RESTRICT。如果在被引用的表中存在相关的外键值,MySQL服务器会拒绝父表的删除或更新操作。一些数据库系统具有延期检查,并且NO ACTION是延期检查。在MySQL中,外键约束被立即检查,所以与之NO ACTION相同
RESTRICT。
SET DEFAULT:这个动作由MySQL解析器认可,但两者
InnoDB并
NDB拒绝包含表定义ON DELETE SET DEFAULT或
ON UPDATE SET DEFAULT条款。
对于未指定的ON DELETE或未ON
UPDATE指定的内容,默认操作始终为RESTRICT。
MySQL支持表中一列与另一列之间的外键引用。(列不能有自己的外键引用。)在这些情况下,“ 子表记录 ”实际上是指同一个表内的相关记录。
在存储生成列外键约束不能用
ON UPDATE CASCADE,ON DELETE SET
NULL,ON UPDATE SET NULL,
ON DELETE SET DEFAULT,或ON UPDATE
SET DEFAULT。
外键约束不能引用虚拟生成的列。
有关InnoDB外键和生成列的限制,请参见
第14.8.1.6节“InnoDB和FOREIGN KEY约束”。
下面是一个简单的例子,通过单列外键关联parent
和child表格:
CREATE TABLE parent(
id INT NOT NULL,
PRIMARY KEY(id)
)ENGINE = INNODB;
CREATE TABLE child(
id INT,
parent_id INT,
INDEX par_ind(parent_id),
FOREIGN KEY(parent_id)
参考父(id)
ON DELETE CASCADE
)ENGINE = INNODB;
一个更复杂的示例,其中一个
product_order表具有另外两个表的外键。一个外键引用表中的两列索引product。另一个引用表中的单列索引customer:
CREATE TABLE产品(
类别INT NOT NULL,ID INT NOT NULL,
价格DECIMAL,
PRIMARY KEY(类别,ID)
)ENGINE = INNODB;
CREATE TABLE客户(
id INT NOT NULL,
PRIMARY KEY(id)
)ENGINE = INNODB;
CREATE TABLE product_order(
无INT NOT NULL AUTO_INCREMENT,
product_category INT NOT NULL,
product_id INT NOT NULL,
customer_id INT NOT NULL,
主键(否),
INDEX(product_category,product_id),
INDEX(customer_id),
FOREIGN KEY(product_category,product_id)
参考产品(类别,ID)
在DELETE RESTRICT上更新级联,
FOREIGN KEY(customer_id)
参考消息(id)
)ENGINE = INNODB;
您可以使用添加一个新的外键约束到现有的表ALTER TABLE。此处显示与此语句的外键相关的语法:
ALTER TABLEtbl_nameADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name](index_col_name,...) 参考文献tbl_name(index_col_name,...) [在删除reference_option] [在更新reference_option]
外键可以是自引用的(参考同一张表)。当您使用外键约束添加到表时
ALTER TABLE,请记住首先创建所需的索引。
您还可以使用下面ALTER TABLE显示的语法删除外键:
ALTER TABLEtbl_nameDROP FOREIGN KEYfk_symbol;
如果在创建外键时该FOREIGN KEY子句包含
CONSTRAINT名称,则可以引用该名称来删除外键。否则,在fk_symbol创建外键时会在内部生成该值。要在放弃外键时查找符号值,请使用
SHOW CREATE TABLE语句,如下所示:
MySQL的>SHOW CREATE TABLE ibtest11c\G*************************** 1. row ******************** ******* 表:ibtest11c 创建表:CREATE TABLE'ibtest11c`( `A` int(11)NOT NULL auto_increment, `D` int(11)NOT NULL默认值为'0', `B`varchar(200)NOT NULL默认'', `C`varchar(175)默认为NULL, 主键(`A`,`D`,`B`), KEY`B`(`B`,`C`), KEY`C`(`C`), CONSTRAINT`0_38775` FOREIGN KEY(`A`,`D`) 参考文献`ibtest11a`(`A`,`D`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT`0_38776` FOREIGN KEY(`B`,`C`) 参考文献`ibtest11a`(`B`,`C`) 在更新级联上删除级联 )ENGINE = INNODB CHARSET = latin1 一排(0.01秒) MySQL的>ALTER TABLE ibtest11c DROP FOREIGN KEY `0_38775`;
在同一ALTER TABLE语句中添加和删除外键
支持ALTER
TABLE ... ALGORITHM=INPLACE但不支持ALTER TABLE ...
ALGORITHM=COPY。
服务器禁止更改外键列,这可能导致引用完整性的丢失。解决方法是ALTER
TABLE ... DROP FOREIGN KEY在更改列定义之前和
ALTER TABLE ... ADD
FOREIGN KEY之后使用。
FOREIGN KEY ...
REFERENCES ...子句中的
表和列标识符可以在反引号(`)内引用。或者,"如果ANSI_QUOTES启用了SQL模式,则可以使用双引号()
。lower_case_table_names系统变量的设置
也被考虑在内。
您可以将子表的外键定义视为SHOW CREATE
TABLE语句输出的一部分:
SHOW CREATE TABLE tbl_name;
您也可以通过查询INFORMATION_SCHEMA.KEY_COLUMN_USAGE
表来获取有关外键的信息
。
您可以在数据库中找到有关InnoDB表
INNODB_SYS_FOREIGN和
INNODB_SYS_FOREIGN_COLS表中使用的外键
的INFORMATION_SCHEMA信息。
mysqldump会生成转储文件中表的正确定义,包括子表的外键。
为了更容易为具有外键关系的表重新加载转储文件,mysqldump会
自动在转储输出中包含一条语句以将其设置
foreign_key_checks为0.这样可以避免在转储重新加载时必须以特定顺序重新加载表的问题。也可以手动设置此变量:
mysql>SET foreign_key_checks = 0;mysql> mysql>SOURCEdump_file_name;SET foreign_key_checks = 1;
这使您可以以任何顺序导入表,如果转储文件包含对于外键没有正确排序的表。它也加快了进口操作。设置
foreign_key_checks为0,也可以是在忽略外键约束有用
LOAD DATA和
ALTER TABLE操作。但是,即使foreign_key_checks = 0MySQL不允许在列引用不匹配列类型的情况下创建外键约束。另外,如果一个表具有外键约束,ALTER
TABLE则不能使用该表来修改该表以使用另一个存储引擎。要更改存储引擎,必须首先删除任何外键约束。
除非你这么做,否则你
不能DROP TABLE为一个被FOREIGN KEY约束引用的表发布SET foreign_key_checks =
0。删除表时,还会删除用于创建该表的语句中定义的任何约束。
如果您重新创建了一个已删除的表,它必须有一个符合引用它的外键约束的定义。如前所述,它必须具有正确的列名称和类型,并且必须在引用键上具有索引。如果这些不满足,MySQL将返回错误1005并引用错误消息中的错误150,这意味着外键约束未正确形成。同样,如果ALTER TABLE由于错误150而导致失败,这意味着对于已更改的表,外键定义将不正确地形成。
对于InnoDB表,您可以InnoDB通过检查MySQL服务器的输出来获得MySQL服务器中最近一次外键错误
的详细解释SHOW ENGINE INNODB
STATUS。
对于熟悉ANSI / ISO SQL标准的用户,请注意,没有任何存储引擎InnoDB能够识别或强制执行MATCH参照完整性约束定义中使用的条款。显式MATCH子句的使用不具有指定的效果,并且原因ON DELETE
和ON UPDATE子句被忽略。由于这些原因,MATCH应避免指定。
MATCHSQL标准中
的子句控制NULL与主键进行比较时如何处理组合(多列)外键中的值。MySQL本质上实现了定义的语义MATCH SIMPLE,允许外键全部或部分地使用NULL。在这种情况下,允许插入包含这样的外键的(子表)行,并且不与引用的(父)表中的任何行匹配。使用触发器可以实现其他语义。
此外,由于性能原因,MySQL要求对引用的列进行索引。但是,系统不强制要求UNIQUE或被声明引用的列
NOT
NULL。对包含NULL
值的非唯一键或键的外键引用的处理,对于诸如UPDATE或的操作没有很好的定义
DELETE
CASCADE。建议您使用仅引用UNIQUE(包括
PRIMARY)和NOT NULL
密钥的外键。
此外,MySQL会解析但忽略“ 内联
REFERENCES规范 ”(如SQL标准中定义的那样),其中引用被定义为列规范的一部分。MySQL REFERENCES仅在作为单独FOREIGN KEY
规范的一部分指定时才接受
子句。对于不支持外键的存储引擎(例如MyISAM),MySQL服务器解析并忽略外键规范。
在某些情况下,MySQL默默地改变列CREATE TABLE或者
ALTER TABLE语句中给出的列规范。这些可能是对数据类型,与数据类型相关的属性或索引规范的更改。
所有更改均受限于65,535字节的内部行大小限制,这可能会导致某些数据类型更改尝试失败。参见第C.10.4节“表列数量和行数限制”。
列,其一部分PRIMARY KEY
是由NOT NULL即使没有声明的方式。
MySQL将其他SQL数据库供应商使用的某些数据类型映射到MySQL类型。请参见 第11.10节“使用其他数据库引擎的数据类型”。
如果包含一个USING子句来指定给定存储引擎不允许使用的索引类型,但是引擎可以使用另一个可用的索引类型而不影响查询结果,则引擎使用可用类型。
如果未启用严格SQL模式,则将
VARCHAR长度规格大于65535 TEXT的VARBINARY列转换为
,并将长度规格大于65535 的
列转换为
BLOB。否则,在这两种情况下都会发生错误。
指定CHARACTER SET binary
字符数据类型的属性会使该列被创建为相应的二进制数据类型:
CHAR变为
BINARY,
VARCHAR变为
VARBINARY,
TEXT变成
BLOB。对于
ENUM和
SET数据类型,这不会发生; 它们按照声明创建。假设你使用这个定义来指定一个表:
CREATE TABLE t ( c1 VARCHAR(10)字符集二进制, c2文本字符集二进制, c3 ENUM('a','b','c')CHARACTER SET二进制 );
结果表格有这样的定义:
CREATE TABLE t ( c1 VARBINARY(10), c2 BLOB, c3 ENUM('a','b','c')CHARACTER SET二进制 );
要查看MySQL是否使用了您指定的数据类型以外的数据类型,请在创建或更改表后创建一个DESCRIBE或
一个SHOW CREATE TABLE语句。
如果使用myisampack压缩表,则会发生其他某些数据类型更改。请参见 第15.2.3.3节“压缩表特征”。
CREATE TABLE支持生成列的规范。生成列的值根据列定义中包含的表达式计算。
生成的列由NDBMySQL NDB Cluster 7.5.3开始的存储引擎支持
。
以下简单的示例显示了存储在直角三角形的边的长度的表
sidea和sideb列,并计算在斜边的长度
sidec(另一侧的平方和的平方根):
CREATE TABLE三角形( sidea DOUBLE, sideb DOUBLE, sidec DOUBLE AS(SQRT(sidea * sidea + sideb * sideb)) ); INSERT INTO三角形(sidea,sideb)VALUES(1,1),(3,4),(6,8);
从表中选择产生这样的结果:
MySQL的> SELECT * FROM triangle;
+ ------- ------- + + -------------------- +
| sidea | sideb | sidec |
+ ------- ------- + + -------------------- +
| 1 | 1 | 1.4142135623730951 |
| 3 | 4 | 5 |
| 6 | 8 | 10 |
+ ------- ------- + + -------------------- +
任何使用该triangle表的应用程序都可以访问斜边值,而无需指定计算它们的表达式。
生成的列定义具有以下语法:
col_namedata_type[GENERATED ALWAYS] AS(expression) [VIRTUAL | STORED] [NOT NULL | 空值] [独特[KEY]] [[PRIMARY] KEY] [评论'string']
AS (
表示该列已生成并定义了用于计算列值的表达式。expression)AS
可能会在之前GENERATED ALWAYS使列的生成特性更加明确。表达式中允许或禁止的构造将在后面讨论。
的VIRTUAL或STORED
关键字表示列的值的存储方式,其具有用于使用列含义:
VIRTUAL:列值不存储,但是在读取行时立即进行评估,紧接在任何
BEFORE触发器之后。虚拟列不需要存储。
InnoDB支持虚拟列上的二级索引。请参见
第13.1.18.9节“二级索引和生成的列”。
STORED:插入或更新行时,将对列值进行评估和存储。存储的列确实需要存储空间并且可以被索引。
默认值是VIRTUAL没有指定关键字。
允许在表格中混合VIRTUAL和
STORED列。
可以给出其他属性以指示列是否被索引或可以是NULL或提供评论。
生成的列表达式必须遵守以下规则。如果表达式包含不允许的构造,则会发生错误。
文字,确定性的内置函数和操作符都是允许的。如果给定表中的相同数据,则函数是确定性的,多个调用产生相同的结果,而与连接的用户无关。的失败这个定义函数的例子:
CONNECTION_ID(),
CURRENT_USER(),
NOW()。
子查询,参数,变量,存储的函数和用户定义的函数是不允许的。
生成的列定义可以引用其他生成的列,但只能引用在表定义中较早的列。生成的列定义可以引用表中的任何基(非生成)列,无论其定义是早于还是晚期。
该AUTO_INCREMENT属性不能在生成的列定义中使用。
一个AUTO_INCREMENT列不能用作在生成的列定义的基柱。
从MySQL 5.7.10开始,如果表达式求值会导致截断或向函数提供不正确的输入,则该
CREATE TABLE语句会因错误而终止,并且DDL操作将被拒绝。
如果表达式的计算结果为与声明列类型不同的数据类型,则根据通常的MySQL类型转换规则对声明类型进行强制转换。请参见 第12.2节“表达式评估中的类型转换”。
如果表达式的任何组件依赖于SQL模式,那么对于表的不同使用可能会出现不同的结果,除非SQL模式在所有用途中都相同。
对于CREATE
TABLE ... LIKE,目标表保留从原始表生成的列信息。
因为CREATE
TABLE ... SELECT目标表不保存关于选定表格中的列是否为生成列的信息。该SELECT语句的
一部分不能将值分配给目标表中的生成列。
通过生成的列进行分区是允许的。请参阅 创建分区表。
在存储生成列外键约束不能用
ON UPDATE CASCADE,ON DELETE SET
NULL,ON UPDATE SET NULL,
ON DELETE SET DEFAULT,或ON UPDATE
SET DEFAULT。
外键约束不能引用虚拟生成的列。
有关InnoDB外键和生成列的限制,请参见
第14.8.1.6节“InnoDB和FOREIGN KEY约束”。
触发器不能使用
或用于
引用生成的列。
NEW.col_nameOLD.col_name
对于INSERT,
REPLACE和
UPDATE,如果生成的列被插入,替换或显式更新,则唯一允许的值是DEFAULT。
视图中生成的列被认为是可更新的,因为可以将其分配给它。但是,如果这样的列被明确更新,则唯一允许的值是
DEFAULT。
生成的列有几个用例,例如:
虚拟生成的列可用作简化和统一查询的一种方式。一个复杂的条件可以定义为一个生成的列,并从表上的多个查询引用,以确保它们全部使用完全相同的条件。
存储生成的列可用作实时高速缓存的复杂条件的物化缓存。
生成的列可以模拟功能索引:使用存储的列来定义功能表达式并将其编入索引。这对于处理无法直接编制索引的类型的列很有用,例如
JSON列; 有关详细示例,请参阅
索引生成的列以提供JSON列索引。
这种方法的缺点是值存储两次; 一次作为生成列的值,一次作为索引。
如果生成的列被索引,则优化程序将识别与列定义匹配的查询表达式,并在查询执行期间适当地使用列中的索引,即使查询未直接按名称引用列。有关细节,请参见 第8.3.10节“生成的列索引的优化器使用”。
例:
假设一个表t1包含
first_name和last_name
列,并且应用程序通常使用如下表达式构造全名:
SELECT CONCAT(first_name,'',last_name)AS full_name FROM t1;
避免编写出表达的一种方法是创建一个视图
v1上t1,其通过使它们简化的应用程序来选择
full_name的情况下直接使用的表达式:
CREATE VIEW v1 AS SELECT *,CONCAT(first_name,'',last_name)AS full_name FROM t1; SELECT full_name FROM v1;
生成的列还使应用程序能够full_name直接选择
,而无需定义视图:
CREATE TABLE t1( first_name VARCHAR(10), last_name VARCHAR(10), full_name VARCHAR(255)AS(CONCAT(first_name,'',last_name)) ); SELECT full_name FROM t1;
InnoDB支持虚拟生成列上的二级索引。其他索引类型不受支持。在虚拟列上定义的二级索引有时被称为“ 虚拟索引 ”。
可以在一个或多个虚拟列上或在虚拟列和常规列或存储的生成列的组合上创建二级索引。包含虚拟列的二级索引可以定义为UNIQUE。
在虚拟生成的列上创建辅助索引时,生成的列值将在索引的记录中实现。如果索引是 覆盖索引(包含查询检索的所有列),则会从索引结构中的物化值中检索生成的列值,而不是“ 即时 ”计算。
有额外的费用写入使用辅助索引时,在虚拟列,由于在计算过程中物化辅助索引记录虚拟列值时,进行考虑INSERT和
UPDATE操作。即使有额外的写入成本,虚拟列上的二级索引也可能优于生成的存储列,这些存储列在聚簇索引中实现,导致需要更多磁盘空间和内存的较大表。如果辅助索引未在虚拟列上定义,则读取会产生额外成本,因为每次检查列的行时都必须计算虚拟列值。
索引虚拟列的值是MVCC记录的,以避免在回滚或清除操作期间不必要地重新生成生成的列值。记录值的数据长度受限于767字节COMPACT和REDUNDANT行格式的索引键限制,以及3072字节DYNAMIC和
COMPRESSED行格式的索引键限制
。
在虚拟列上添加或删除二级索引是就地操作。
在5.7.16之前,外键约束不能引用在虚拟生成列上定义的辅助索引。
在MySQL 5.7.13及更早版本中,InnoDB不允许在索引生成的虚拟列的基本列上使用级联参考操作定义外键约束。MySQL 5.7.14中解除了这个限制。
如别处所述,JSON
列不能直接编制索引。要创建一个间接引用此列的索引,可以定义一个生成的列,以提取应该编制索引的信息,然后在生成的列上创建一个索引,如下例所示:
mysql>CREATE TABLE jemp (- >c JSON,- >g INT GENERATED ALWAYS AS (c->"$.id"),- >INDEX i (g)- >);查询OK,0行受影响(0.28秒) MySQL的>INSERT INTO jemp (c) VALUES>('{"id": "1", "name": "Fred"}'), ('{"id": "2", "name": "Wilma"}'),>('{"id": "3", "name": "Barney"}'), ('{"id": "4", "name": "Betty"}');查询OK,4行受影响(0.04秒) 记录:4个重复:0个警告:0 mysqlSELECT c->>"$.name" AS name>>FROM jemp WHERE g > 2;+ -------- + | 名称| + -------- + | 巴尼| | 贝蒂| + -------- + 设置2行(0.00秒) mysqlEXPLAIN SELECT c->>"$.name" AS name>>FROM jemp WHERE g > 2\G*************************** 1. row ******************** ******* ID:1 select_type:SIMPLE 表:jemp 分区:NULL 键入:范围 possible_keys:我 关键:我 key_len:5 ref:NULL 行数:2 过滤:100.00 额外:在哪里使用 1行,1警告(0.00秒) MySQL的>SHOW WARNINGS\G*************************** 1. row ******************** ******* 级别:注意 代码:1003 消息:/ * select#1 * / select json_unquote(json_extract(`test`.`jemp`.`c`,'$。name')) AS```````test`.`jemp`其中(`test`.`jemp`.`g`> 2) 一排(0.00秒)
(在这个例子中,我们封装了最后一条语句的输出以适合查看区域。)
该
->
操作符在MySQL 5.7.9及更高版本中受支持。该
->>
运营商支持开始使用MySQL 5.7.13。
当您EXPLAIN在
SELECT包含一个或多个使用->or ->>
运算符的表达式或其他SQL语句上使用时
,将使用JSON_EXTRACT()和(如果需要)将这些表达式转换为它们的等价形式JSON_UNQUOTE(),如此处SHOW
WARNINGS紧接在此EXPLAIN语句后面
的输出中所示:
mysqlEXPLAIN SELECT c->>"$.name">>FROM jemp WHERE g > 2 ORDER BY c->"$.name"\G*************************** 1. row ******************** ******* ID:1 select_type:SIMPLE 表:jemp 分区:NULL 键入:范围 possible_keys:我 关键:我 key_len:5 ref:NULL 行数:2 过滤:100.00 额外:使用where; 使用filesort 1行,1警告(0.00秒) MySQL的>SHOW WARNINGS\G*************************** 1. row ******************** ******* 级别:注意 代码:1003 消息:/ * select#1 * / select json_unquote(json_extract(`test`.`jemp`.`c`,'$。name'))AS `c - >>“$。name``from`test`.`jemp` where(`test`.`jemp`.`g`> 2)order by json_extract(`test`.`jemp`.`c`, '$。名称') 一排(0.00秒)
看到的的描述
->
和
->>
操作员,以及那些的
JSON_EXTRACT()和
JSON_UNQUOTE()功能,附加信息和示例。
这种技术也可以用来提供索引,间接引用其他类型的不能被直接索引的GEOMETRY列,例如列。
也可以在MySQL NDB Cluster 7.5.3及更高版本中对JSON列进行间接索引,但需满足以下条件:
CREATE TABLE用于创建jempn此处显示的表格
的语句是jemp前面显示的表格的一个版本,其修改使其与NDB以下内容兼容
:
CREATE TABLE jempn( BIGINT(20)NOT NULL AUTO_INCREMENT PRIMARY KEY, c JSON DEFAULT NULL, g INT一直生成(c - >“$。name”)存储, INDEX i(g) )ENGINE = NDB;
我们可以使用以下INSERT语句填充此表
:
INSERT INTO jempn(a,c)VALUES
(NULL,'{“id”:“1”,“name”:“Fred”}'),
(NULL,'{“id”:“2”,“name”:“Wilma”}'),
(NULL,'{“id”:“3”,“name”:“Barney”}'),
(NULL,'{“id”:“4”,“name”:“Betty”}');
现在NDB可以使用索引i,如下所示:
MySQL的>EXPLAIN SELECT c->>"$.name" AS name FROM jempn WHERE g > 2\G*************************** 1. row ******************** ******* ID:1 select_type:SIMPLE 表:jempn 分区:p0,p1 键入:范围 possible_keys:我 关键:我 key_len:5 ref:NULL 行数:3 过滤:100.00 额外:使用推送条件(`test`.`jempn`.`g`> 2) 1行,1警告(0.00秒) MySQL的>SHOW WARNINGS\G*************************** 1. row ******************** ******* 级别:注意 代码:1003 消息:/ *选择#1 * /选择 json_unquote(json_extract(`test`.`jempn`.`c`,'$。name'))AS`name` from `test`.`jempn` where(`test`.```empn`.`g`> where 2) 一排(0.00秒)
您应该记住,存储的生成列使用DataMemory,并且该列
上的索引使用
IndexMemory。
在MySQL NDB Cluster 7.5.2及更高版本中,a CREATE TABLE或ALTER
TABLE语句中的表注释
也可用于指定一个
NDB_TABLE选项,该选项由字符串后面的一个或多个名称 - 值对(如果需要用逗号分隔)组成NDB_TABLE=。这里显示了名称和值语法的完整语法:
COMMENT =“NDB_TABLE =ndb_table_option[,ndb_table_option[,...]]”ndb_table_option: NOLOGGING = {1 | 0} | READ_BACKUP = {1 | 0} | PARTITION_BALANCE = {FOR_RP_BY_NODE | FOR_RA_BY_NODE | FOR_RP_BY_LDM | FOR_RA_BY_LDM | FOR_RA_BY_LDM_X_2 | FOR_RA_BY_LDM_X_3 | FOR_RA_BY_LDM_X_4} | FULLY_REPLICATED = {1 | 0}
引用字符串内不允许有空格。该字符串不区分大小写。
NDB在接下来的几段中将更详细地描述可以以这种方式设置为评论的一部分
的四个表格选项。
NOLOGGING:使用1对应于已
ndb_table_no_logging启用,但没有实际效果。作为占位符提供,主要是为了完整的ALTER TABLE
陈述。
READ_BACKUP:将此选项设置为1具有与ndb_read_backup启用相同的效果
; 可以从任何副本中读取。从MySQL NDB Cluster 7.5.3开始,您可以READ_BACKUP使用ALTER TABLE类似于此处显示的语句在线设置现有表(Bug#80858,Bug#23001617)
:
ALTER TABLE ... ALGORITHM = INPLACE,COMMENT =“NDB_TABLE = READ_BACKUP = 1”; ALTER TABLE ... ALGORITHM = INPLACE,COMMENT =“NDB_TABLE = READ_BACKUP = 0”;
在MySQL NDB Cluster 7.5.4之前,设置
READ_BACKUP为1也导致
FRAGMENT_COUNT_TYPE设置为
ONE_PER_LDM_PER_NODE_GROUP。
有关ALGORITHM
选项的更多信息ALTER TABLE,请参见
第13.1.8.2节“NDB集群中的ALTER TABLE联机操作”。
PARTITION_BALANCE:提供对分配的分配和放置的额外控制。支持以下四种方案:
FOR_RP_BY_NODE:每个节点一个分区。
每个节点上只有一个LDM存储主分区。每个分区在所有节点上存储在相同的LDM(相同的ID)中。
FOR_RA_BY_NODE:每个节点组一个分区。
每个节点都存储一个分区,该分区可以是主副本或备份副本。每个分区都存储在所有节点上的相同LDM中。
FOR_RP_BY_LDM:每个节点上每个LDM的一个分区; 默认。
这与MySQL NDB Cluster 7.5.2之前的行为相同,除了将分区映射到LDM稍微不同之外,从LDM 0开始并为每个节点组放置一个分区,然后转到下一个LDM。
在MySQL NDB Cluster 7.5.4和更高版本中,如果READ_BACKUP设置为1 ,则使用此设置。(错误#82634,错误#24482114)
FOR_RA_BY_LDM:每个节点组中的每个LDM一个分区。
这些分区可以是主分区或备份分区。
在MySQL NDB Cluster 7.5.4之前,如果READ_BACKUP设置为1 ,则使用此设置。
FOR_RA_BY_LDM_X_2:每个节点组中的每个LDM有两个分区。
这些分区可以是主分区或备份分区。
此设置已添加到NDB 7.5.4中。
FOR_RA_BY_LDM_X_3:每个节点组中的每个LDM有三个分区。
这些分区可以是主分区或备份分区。
此设置已添加到NDB 7.5.4中。
FOR_RA_BY_LDM_X_4:每个节点组中每个LDM有四个分区。
这些分区可以是主分区或备份分区。
此设置已添加到NDB 7.5.4中。
从NDB 7.5.4开始,PARTITION_BALANCE
是设置每个表的分区数的首选接口。MAX_ROWS从NDB 7.5.4开始,不推荐使用强制分区数目,在NDB 7.6中继续支持分区数目以实现向后兼容性,但在未来版本的MySQL NDB集群中可能会被删除。(错误#81759,错误#23544301)
在此之前的MySQL NDB簇7.5.4,
PARTITION_BALANCE被命名
FRAGMENT_COUNT_TYPE,并接受其价值的一个(在相同的顺序,上市只是所示)ONE_PER_NODE,
ONE_PER_NODE_GROUP,
ONE_PER_LDM_PER_NODE,或
ONE_PER_LDM_PER_NODE_GROUP。(错误#81761,错误#23547525)
FULLY_REPLICATED控制表是否完全复制,即每个数据节点是否具有表的完整副本。要启用表的完整复制,请使用FULLY_REPLICATED=1。
该设置也可以使用ndb_fully_replicated系统变量进行控制
。将其设置为ON默认启用所有新NDB表的选项; 缺省值是
OFF,它保留了以前的行为(如在引入对完全复制表的支持之前,在MySQL NDB Cluster 7.5.1及更早的版本中)。该
ndb_data_node_neighbour系统变量也可用于完全复制表,以确保当被访问的完全复制表中,我们访问的是本地本MySQL服务器的数据节点。
这里显示了CREATE TABLE创建NDB表时使用这种注释
的语句示例:
的MySQL>CREATE TABLE t1 (>c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,>c2 VARCHAR(100),>c3 VARCHAR(100) )>ENGINE=NDB>COMMENT="NDB_TABLE=READ_BACKUP=0,PARTITION_BALANCE=FOR_RP_BY_NODE";
注释显示为输出的一部分
SHOW CREATE TABLE。评论的文本也可以通过查询MySQL信息模式TABLES表获得,如下例所示:
mysqlSELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT>>FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1";+ ------------ + -------------- + --------------------- ------------------------------------- + | TABLE_NAME | TABLE_SCHEMA | TABLE_COMMENT | + ------------ + -------------- + --------------------- ------------------------------------- + | t1 | c | NDB_TABLE = READ_BACKUP = 0,PARTITION_BALANCE = FOR_RP_BY_NODE | | t1 | d | | + ------------ + -------------- + --------------------- ------------------------------------- + 设置2行(0.00秒)
该评论语法也支持
表格的ALTER TABLE语句
NDB。请记住,使用的表格注释会ALTER TABLE替换表中可能存在的任何现有注释。
MySQL的>ALTER TABLE t1 COMMENT="NDB_TABLE=PARTITION_BALANCE=FOR_RA_BY_NODE";查询OK,0行受影响(0.40秒) 记录:0重复:0警告:0 mysqlSELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT>>FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1";+ ------------ + -------------- + --------------------- ----------------------------- + | TABLE_NAME | TABLE_SCHEMA | TABLE_COMMENT | + ------------ + -------------- + --------------------- ----------------------------- + | t1 | c | NDB_TABLE = PARTITION_BALANCE = FOR_RA_BY_NODE | | t1 | d | | + ------------ + -------------- + --------------------- ----------------------------- + 设置2行(0.01秒)
您还PARTITION_BALANCE可以在ndb_desc的输出中看到该选项
的值
。ndb_desc还显示是否为该表设置READ_BACKUP和
FULLY_REPLICATED选项。有关更多信息,请参阅此程序的说明。
由于该READ_BACKUP值未被转移到由ALTER
TABLE语句设置的新评论,因此不再使用SQL来检索之前为其设置的值。为避免发生这种情况,建议您保留现有注释字符串中的任何此类值,如下所示:
mysqlSELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT>>FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1";+ ------------ + -------------- + --------------------- ------------------------------------- + | TABLE_NAME | TABLE_SCHEMA | TABLE_COMMENT | + ------------ + -------------- + --------------------- ------------------------------------- + | t1 | c | NDB_TABLE = READ_BACKUP = 0,PARTITION_BALANCE = FOR_RP_BY_NODE | | t1 | d | | + ------------ + -------------- + --------------------- ------------------------------------- + 设置2行(0.00秒) MySQL的>ALTER TABLE t1 COMMENT="NDB_TABLE=READ_BACKUP=0,PARTITION_BALANCE=FOR_RA_BY_NODE";查询OK,0行受影响(1.56秒) 记录:0重复:0警告:0 mysqlSELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT>>FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1";+ ------------ + -------------- + --------------------- ------------------------------------------- + | TABLE_NAME | TABLE_SCHEMA | TABLE_COMMENT | + ------------ + -------------- + --------------------- ------------------------------------------- + | t1 | c | NDB_TABLE = READ_BACKUP = 0,PARTITION_BALANCE = FOR_RA_BY_NODE | | t1 | d | | + ------------ + -------------- + --------------------- ------------------------------------------- + 设置2行(0.01秒)
创建表空间tablespace_nameInnoDB和NDB: 添加数据文件'file_name' 仅限InnoDB: [FILE_BLOCK_SIZE =值] 仅限NDB: 使用LOGFILE GROUPlogfile_group[EXTENT_SIZE [=]extent_size] [INITIAL_SIZE [=]initial_size] [AUTOEXTEND_SIZE [=]autoextend_size] [MAX_SIZE [=]max_size] [NODEGROUP [=]nodegroup_id] [等待] [评论[=]'string'] InnoDB和NDB: [ENGINE [=]engine_name]
该语句用于创建表空间。精确的语法和语义取决于使用的存储引擎。在标准的MySQL 5.7版本中,这总是一个
InnoDB表空间。MySQL NDB Cluster 7.5还支持使用NDB存储引擎的表空间
InnoDB。
使用InnoDB创建的表空间
CREATE TABLESPACE称为
通用表空间。这是一个共享的表空间,类似于系统表空间。它可以容纳多个表格,并支持所有表格行格式。通用表空间可以在相对于或独立于MySQL数据目录的位置创建。
创建InnoDB常规表空间后,可以使用或
向表空间添加表。
CREATE
TABLE tbl_name ... TABLESPACE [=]
tablespace_nameALTER TABLE
tbl_name TABLESPACE [=]
tablespace_name
有关更多信息,请参见第14.7.9节“InnoDB常规表空间”。
该语句用于创建一个表空间,该表空间可以包含一个或多个数据文件,为NDB集群磁盘数据表提供存储空间(请参见第21.5.13节“NDB集群磁盘数据表”)。使用此语句创建一个数据文件并将其添加到表空间。其他数据文件可以通过使用ALTER TABLESPACE
语句添加到表空间中(请参见第13.1.9节“ALTER TABLESPACE语法”)。
所有NDB群集磁盘数据对象共享相同的名称空间。这意味着每个磁盘数据对象必须是唯一命名的(而不仅仅是给定类型的每个磁盘数据对象)。例如,您不能拥有同名的表空间和日志文件组,或者具有相同名称的表空间和数据文件。
一个或多个UNDO日志文件的日志文件组必须分配给要使用USE LOGFILE GROUP子句创建的表空间
。
logfile_group必须是使用创建的现有日志文件组CREATE LOGFILE
GROUP(请参见第13.1.15节“CREATE LOGFILE GROUP语法”)。多个表空间可以使用相同的日志文件组进行
UNDO日志记录。
在设置EXTENT_SIZE或时
INITIAL_SIZE,您可以选择使用与英文中使用的数字类似的单字母缩写的数量级my.cnf。通常,这是字母之一M(对于兆字节)或
G(对于千兆字节)。
INITIAL_SIZE并EXTENT_SIZE
受四舍五入的影响如下:
EXTENT_SIZE 被四舍五入到32K的整数倍。
INITIAL_SIZE是圆形的
向下到32K最接近的整倍数; 这个结果被四舍五入到最接近的整数倍EXTENT_SIZE(任何四舍五入后)。
刚刚描述的舍入是显式完成的,并且当执行任何这样的舍入时,MySQL服务器发出警告。NDB内核也使用舍入值来计算
INFORMATION_SCHEMA.FILES列值和其他用途。但是,为避免意外的结果,我们建议您始终使用32K的整数倍来指定这些选项。
何时CREATE TABLESPACE与
ENGINE [=] NDB每个群集数据节点上创建一个表空间和关联的数据文件。您可以验证数据文件是否已创建,并通过查询INFORMATION_SCHEMA.FILES表获取有关它们的信息
。(请参阅本节后面的示例。)
(请参见第24.8节“INFORMATION_SCHEMA文件表”)。
ADD DATAFILE:定义表空间数据文件的名称; 这个选项总是需要的。一个
InnoDB表空间仅支持单个数据文件,其名称必须包括.ibd
扩展名。NDB簇表空间支持多个数据文件,这些文件可以具有任何合法的文件名; 通过使用ALTER TABLESPACE
语句创建后,可以将更多数据文件添加到NDB Cluster表空间中。
ALTER TABLESPACE不受支持
InnoDB。
要将数据文件放在MySQL数据目录(datadir)以外的位置,请包含绝对目录路径或相对于MySQL数据目录的路径。如果不指定路径,则表空间将在MySQL数据目录中创建。在MySQL数据目录
之外创建表空间时,将在MySQL数据目录中创建一个
isl文件InnoDB。
为避免与隐式创建的每个表文件表空间冲突,不支持在MySQL数据目录下的子目录中创建常规表空间。另外,在MySQL数据目录之外创建一个通用表空间时,目录必须在创建表空间之前存在。
的,包括路径(可选),必须用单或双引号引用。文件名(不包括文件的任何
“ .ibd ”扩展名file_nameInnoDB
)和目录名必须至少有一个字节的长度。零长度的文件名和目录名称不受支持。
FILE_BLOCK_SIZE:该选项 - 特定于InnoDB并且被忽略 -
NDB定义表空间数据文件的块大小。如果您不指定此选项,则
FILE_BLOCK_SIZE默认为
innodb_page_size。
FILE_BLOCK_SIZE当您打算使用表空间来存储压缩
InnoDB表(ROW_FORMAT=COMPRESSED)时需要。
如果FILE_BLOCK_SIZE等于
innodb_page_size,表空间可以含有具有未压缩的行格式仅表(COMPACT,
REDUNDANT,或DYNAMIC)。表使用的物理页面大小COMPRESSED与未压缩的表的物理页大小
不同; 这意味着压缩表和未压缩表不能共存于同一个表空间中。
对于包含压缩表的常规表空间,
FILE_BLOCK_SIZE必须指定该FILE_BLOCK_SIZE值,并且该值必须是与该
值有关的有效压缩页面大小
innodb_page_size。另外,压缩表(KEY_BLOCK_SIZE)的物理页面大小必须等于
FILE_BLOCK_SIZE/1024。例如,如果
innodb_page_size=16K和
FILE_BLOCK_SIZE=8K,该
KEY_BLOCK_SIZE表必须为8欲了解更多信息,请参见第14.7.9,“InnoDB的总表空间”。
USE LOGFILE GROUP:必需的
NDB,这是以前使用的日志文件组的名称CREATE LOGFILE
GROUP。不支持InnoDB,因为出现错误而失败。
EXTENT_SIZE:这个选项是特定于NDB的,InnoDB不支持它,它在失败时会出现错误。EXTENT_SIZE设置属于表空间的任何文件使用的区的大小(以字节为单位)。默认值是1M。最小尺寸为32K,理论最大值为2G,但实际最大尺寸取决于许多因素。在大多数情况下,更改盘区大小不会对性能产生任何可衡量的影响,并且除了最不寻常的情况外,建议使用默认值。
的程度是磁盘空间分配的单位。一个范围充满了在使用另一个范围之前该范围可以包含的尽可能多的数据。理论上,每个数据文件最多可以使用65,535(64K)个区段; 但是,建议的最大值是32,768(32K)。单个数据文件的建议最大大小为32G,即每个区域32K扩展区大小×1 MB。另外,一旦将分区分配给给定的分区,它就不能用于存储来自不同分区的数据; 一个盘区不能存储来自多个分区的数据。这意味着,例如,具有单个数据文件的表空间INITIAL_SIZE(在下面的项目中描述)是256 MB,
EXTENT_SIZE 是128M只有两个扩展盘区,因此可用于存储来自至多两个不同磁盘数据表分区的数据。
您可以通过查询INFORMATION_SCHEMA.FILES表来查看给定数据文件中有多少数据块
空闲空间,从而得出文件中剩余多少空间的估计。有关进一步的讨论和示例,请参见
第24.8节“INFORMATION_SCHEMA文件表”。
INITIAL_SIZE:该选项特定于
NDB并且不受其支持
InnoDB,并且在出现错误时失败。
该INITIAL_SIZE参数设置特定使用的数据文件的总大小(以字节为单位)
ADD DATATFILE。一旦创建了这个文件,它的大小就不能改变; 但是,您可以使用添加更多数据文件到表空间
ALTER
TABLESPACE ... ADD DATAFILE。
INITIAL_SIZE是可选的; 其默认值是134217728(128 MB)。
在32位系统上,支持的最大值为
INITIAL_SIZE4294967296(4 GB)。
AUTOEXTEND_SIZE:目前被MySQL忽略; 保留以备将来使用。无论使用哪种存储引擎,在任何版本的MySQL 5.7或MySQL NDB Cluster 7.5中都不起作用。
MAX_SIZE:目前被MySQL忽略; 保留以备将来使用。无论使用哪种存储引擎,在任何版本的MySQL 5.7或MySQL NDB Cluster 7.5中都不起作用。
NODEGROUP:目前被MySQL忽略; 保留以备将来使用。无论使用哪种存储引擎,在任何版本的MySQL 5.7或MySQL NDB Cluster 7.5中都不起作用。
WAIT:目前被MySQL忽略; 保留以备将来使用。无论使用哪种存储引擎,在任何版本的MySQL 5.7或MySQL NDB Cluster 7.5中都不起作用。
COMMENT:目前被MySQL忽略; 保留以备将来使用。无论使用哪种存储引擎,在任何版本的MySQL 5.7或MySQL NDB Cluster 7.5中都不起作用。
ENGINE:定义使用表空间的存储引擎,其中
engine_name是存储引擎的名称。目前,只有InnoDB
标准MySQL 5.7版本支持存储引擎。MySQL的NDB簇7.5支持
NDB和InnoDB
表空间。如果未指定该选项,则default_storage_engine使用系统变量的值
ENGINE。
有关MySQL表空间命名的规则,请参见
第9.2节“模式对象名称”。除了这些规则之外,不允许使用斜杠字符(“ / ”),也不能使用以innodb_前缀开头的名称,因为此前缀保留供系统使用。
表空间不支持临时表。
该TABLESPACE选项可以与被用于
CREATE TABLE或
ALTER TABLE要分配
InnoDB表分区或子分区的一般表空间,一个单独的文件,每个表的表空间,或系统表空间。TABLESPACEMySQL 5.7中添加了对表分区和子分区的选项支持。所有分区必须属于同一个存储引擎。有关更多信息,请参见
第14.7.9节“InnoDB常规表空间”。
innodb_file_per_table,
innodb_file_format和
innodb_file_format_max
设置对CREATE
TABLESPACE操作没有影响。
innodb_file_per_table不需要启用。不管文件格式设置如何,常规表空间都支持所有表格行格式。同样,CREATE TABLE ...
TABLESPACE不管文件格式设置如何,通用表空间都支持添加任何行格式的表格
。
innodb_strict_mode不适用于一般的表空间。表空间管理规则严格独立执行
innodb_strict_mode。如果
CREATE TABLESPACE参数不正确或不兼容,无论innodb_strict_mode设置如何,操作都会失败
。当使用CREATE TABLE ...
TABLESPACE或
将表添加到常规表空间时
ALTER TABLE ...
TABLESPACE,innodb_strict_mode将忽略该语句,
但语句的计算方式与innodb_strict_mode启用该语句时相同
。
使用DROP TABLESPACE删除表空间。在删除表空间DROP TABLE之前,必须从表空间
中删除所有表。在删除NDB集群表空间之前,您还必须使用一个或多个ALTER
TABLESPACE ... DROP DATATFILE语句删除其所有数据文件
。请参见
第21.5.13.1节“NDB群集磁盘数据对象”。
InnoDB添加到InnoDB常规表空间
的表的
所有部分驻留在常规表空间中,包括索引和
BLOB页面。
对于NDB分配给表空间的表,只有未索引的列才存储在磁盘上,并且实际使用表空间数据文件。所有NDB表的索引和索引列始终保留在内存中。
与系统表空间类似,截断或删除存储在通用表空间中的表可在通用表空间.ibd数据文件的内部创建空闲空间,该
数据文件只能用于新InnoDB数据。空间不会释放回操作系统,因为它是用于每个表文件的表空间。
常规表空间不与任何数据库或模式关联。
ALTER TABLE ...
DISCARD TABLESPACE并且
ALTER TABLE
...IMPORT TABLESPACE不支持属于常规表空间的表。
服务器使用表空间级别元数据锁定引用常规表空间的DDL。相比之下,服务器使用表级别元数据锁定引用文件每表的表空间的DDL。
生成的或现有的表空间不能更改为常规表空间。
由于添加了新的表标志,只能在MySQL 5.7.6或更高版本中打开存储在常规表空间中的表。
常规表空间名称和每个文件表空间名称之间没有冲突。 一般表空间名称中不允许出现在每个表文件表空间名称中的“ / ”字符。
这个例子演示了创建一个通用表空间并添加三个不同行格式的未压缩表。
mysql>CREATE TABLESPACE `ts1`- >ADD DATAFILE 'ts1.ibd'- >ENGINE=INNODB;查询OK,0行受影响(0.01秒) mysql>CREATE TABLE t1 (c1 INT PRIMARY KEY)- >TABLESPACE ts1- >ROW_FORMAT=REDUNDANT;查询OK,0行受影响(0.00秒) mysql>CREATE TABLE t2 (c1 INT PRIMARY KEY)- >TABLESPACE ts1- >ROW_FORMAT=COMPACT;查询OK,0行受影响(0.00秒) mysql>CREATE TABLE t3 (c1 INT PRIMARY KEY)- >TABLESPACE ts1- >ROW_FORMAT=DYNAMIC;查询OK,0行受影响(0.00秒)
此示例演示如何创建常规表空间并添加压缩表。该示例假设默认
innodb_page_size值为16K。在
FILE_BLOCK_SIZE8192要求压缩表有KEY_BLOCK_SIZE8个。
mysql> CREATE TABLESPACE`ts2`
- > ADD DATAFILE'ts2.ibd'
- > FILE_BLOCK_SIZE = 8192
- > ENGINE = INNODB;
查询OK,0行受影响(0.01秒)
mysql> CREATE TABLE t4(c1 INT PRIMARY KEY)
- > TABLESPACE ts2
- > ROW_FORMAT = COMPRESSED
- > KEY_BLOCK_SIZE = 8;
查询OK,0行受影响(0.00秒)
假设您希望创建一个名为myts使用数据文件命名
的NDB群集磁盘数据表空间mydata-1.dat。一个NDB
表空间总是需要使用由一个或多个撤消日志文件,日志文件组。在这个例子中,我们首先创建一个名为的日志文件组mylg,其中包含一个名为的撤消长文件myundo-1.dat,使用以下CREATE LOGFILE GROUP显示的
语句:
mysql>CREATE LOGFILE GROUP myg1- >ADD UNDOFILE 'myundo-1.dat'- >ENGINE=NDB;查询OK,0行受影响(3.29秒)
现在您可以使用以下语句创建之前描述的表空间:
mysql>CREATE TABLESPACE myts- >ADD DATAFILE 'mydata-1.dat'- >USE LOGFILE GROUP mylg- >ENGINE=NDB;查询OK,0行受影响(2.98秒)
您现在可以使用CREATE TABLE带有TABLESPACE和STORAGE DISK
选项的语句
创建磁盘数据表
,如下所示:
mysql>CREATE TABLE mytable (- >id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,- >lname VARCHAR(50) NOT NULL,- >fname VARCHAR(50) NOT NULL,- >dob DATE NOT NULL,- >joined DATE NOT NULL,- >INDEX(last_name, first_name)- >)- >TABLESPACE myts STORAGE DISK- >ENGINE=NDB;查询OK,0行受影响(1.41秒)
需要注意的是只有这一点非常重要dob和
joined列从mytable
实际存储在磁盘上,由于事实
id,lname和
fname列所有索引。
如前所述,当CREATE TABLESPACE
与ENGINE [=] NDB每个NDB集群数据节点一起使用时,会创建表空间和关联的数据文件。您可以通过查询INFORMATION_SCHEMA.FILES表来验证数据文件是否已创建并获取有关它们的信息
,如下所示:
mysql>SELECT FILE_NAME, FILE_TYPE, LOGFILE_GROUP_NAME, STATUS, EXTRA- >FROM INFORMATION_SCHEMA.FILES- >WHERE TABLESPACE_NAME = 'myts';+ -------------- + ------------ + -------------------- + -------- + ---------------- + | file_name | file_type | logfile_group_name | 状态| 额外| + -------------- + ------------ + -------------------- + -------- + ---------------- + | mydata-1.dat | DATAFILE | mylg | 正常| CLUSTER_NODE = 5 | | mydata-1.dat | DATAFILE | mylg | 正常| CLUSTER_NODE = 6 | | NULL | TABLESPACE | mylg | 正常| NULL | + -------------- + ------------ + -------------------- + -------- + ---------------- + 3行(0.01秒)
有关其他信息和示例,请参见 第21.5.13.1节“NDB群集磁盘数据对象”。
创建
[DEFINER = { user| 当前用户 }]
TRIGGER
ON FOR EACH ROWtrigger_name
trigger_time trigger_eventtbl_name
[ trigger_order]
trigger_body
trigger_time:{BEFORE | AFTER}
trigger_event:{INSERT | 更新| DELETE}
trigger_order:{关注| PRECEDES}other_trigger_name
该声明创建了一个新的触发器。触发器是一个与表关联的命名数据库对象,当表发生特定事件时会激活该对象。该触发器与名为的表相关联,该表
tbl_name必须引用永久表。您不能将触发器与TEMPORARY表或视图相关联
。
触发器名称存在于模式名称空间中,这意味着所有触发器在模式中都必须具有唯一的名称。不同模式中的触发器可以具有相同的名称。
本节介绍CREATE
TRIGGER语法。有关其他讨论,请参见
第23.3.1节“触发器语法和示例”。
CREATE TRIGGER需要TRIGGER与触发器关联的表的
特权。该声明可能还需要
SUPER特权,具体取决于该
DEFINER值,如本节后面所述。如果启用二进制日志记录,则CREATE
TRIGGER可能需要
SUPER权限,如
第23.7节“存储程序的二进制日志记录”中所述。
该DEFINER子句确定在触发器激活时检查访问权限时要使用的安全上下文,如本节后面所述。
trigger_time是触发器动作时间。它可以是BEFORE或
AFTER以指示该触发之前或之后的每一行进行修改激活。
基本列值检查发生在触发器激活之前,因此您不能使用BEFORE触发器将不适合列类型的值转换为有效值。
trigger_event表示激活触发器的操作类型。这些
trigger_event值是允许的:
这trigger_event不代表激活触发器的字面类型的SQL语句,因为它代表了一种表操作类型。例如,
INSERT触发器不仅可以激活INSERT语句,还可以
激活LOAD DATA语句,因为这两个语句都会将行插入表中。
一个潜在的令人困惑的例子是INSERT
INTO ... ON DUPLICATE KEY UPDATE ...语法:一个
BEFORE INSERT触发器为每一行激活,随后是AFTER INSERT触发器或触发器BEFORE UPDATE和AFTER
UPDATE触发器,具体取决于行是否有重复键。
级联外键操作不会激活触发器。
可以为具有相同触发事件和操作时间的给定表定义多个触发器。例如,您可以BEFORE UPDATE为表格添加两个触发器。默认情况下,具有相同触发事件和操作时间的触发器按其创建顺序激活。要影响触发顺序,请指定一个trigger_order子句,该子句指示FOLLOWS或
PRECEDES还有具有相同触发事件和操作时间的现有触发的名称。随着
FOLLOWS,新的触发器在现有的触发器之后激活。使用时PRECEDES,新触发器在现有触发器之前激活。
trigger_body是触发器激活时要执行的语句。要执行多个语句,请使用
BEGIN ... END
复合语句构造。这也使您能够使用存储例程中允许的相同语句。请参见
第13.6.1节“BEGIN ... END复合语句语法”。触发器中不允许使用某些语句; 参见第C.1节“对存储程序的限制”。
在触发器正文中,您可以使用别名OLD和引用主题表中的列(与触发器关联的表)
NEW。
在更新或删除之前引用现有行的列。
指的是要插入的新行的列或更新后的现有行。
OLD.col_nameNEW.col_name
触发器不能使用
或用于
引用生成的列。有关生成列的信息,请参见第13.1.18.8节“CREATE TABLE和Generated Columns”。
NEW.col_nameOLD.col_name
sql_mode当创建触发器时,
MySQL存储系统变量设置,并始终使用此设置执行触发器主体,
而不管触发器开始执行时的当前服务器SQL模式如何。
该DEFINER子句指定在触发器激活时检查访问权限时要使用的MySQL帐户。如果user给出值,它应该指定为MySQL账户
,
或
。缺省
值是执行语句的用户
。这与
明确指定相同。
'user_name'@'host_name'CURRENT_USERCURRENT_USER()DEFINERCREATE TRIGGERDEFINER = CURRENT_USER
如果您指定了该DEFINER子句,则这些规则将确定有效的DEFINER用户值:
如果您没有SUPER
权限,唯一允许的user
值是您自己的帐户,无论是按字面还是使用指定CURRENT_USER。您无法将定义者设置为某个其他帐户。
如果您有SUPER
权限,则可以指定任何语法上有效的帐户名称。如果该帐户不存在,则会生成警告。
虽然可以用不存在的DEFINER帐户创建触发器
,但直到帐户实际存在才激活触发器并不是一个好主意。否则,有关特权检查的行为是未定义的。
DEFINER在检查触发器特权时,
MySQL会将用户考虑在内,如下所示:
在CREATE TRIGGER时间,谁发出语句的用户必须有
TRIGGER特权。
在触发器激活时,将针对DEFINER用户检查权限
。该用户必须具有以下权限:
有关触发器安全性的更多信息,请参见 第23.6节“存储程序和视图的访问控制”。
在触发器主体中,
CURRENT_USER()函数返回用于在触发器激活时检查权限的帐户。这是DEFINER用户,而不是其操作导致触发器被激活的用户。有关触发器中用户审计的信息,请参见
第6.3.12节“基于SQL的MySQL帐户活动审计”。
如果您使用LOCK TABLES锁定具有触发器的表格,则触发器中使用的表格也将被锁定,如
第13.3.5.2节“锁定表格和触发器”中所述。
有关触发器使用的更多讨论,请参见 第23.3.1节“触发器语法和示例”。
创建
[或替换]
[ALGORITHM = {未定义| MERGE | 不是Temptable}]
[DEFINER = { user| 当前用户 }]
[SQL SECURITY {DEFINER | INVOKER}]
VIEW view_name[(column_list)]
如 select_statement
[WITH [CASCADED | LOCAL]检查选项]
该CREATE VIEW语句创建一个新视图,或者在OR
REPLACE给出子句的情况下替换现有视图。如果视图不存在,
CREATE OR REPLACE
VIEW则与之相同CREATE
VIEW。如果视图确实存在,则
CREATE OR REPLACE
VIEW替换它。
有关视图使用限制的信息,请参见 第C.5节“视图限制”。
这select_statement是一个
SELECT声明,提供了视图的定义。(从视图中选择实际上使用该SELECT
语句。)select_statement可以从基表或其他视图中进行选择。
视图定义在创建时被“ 冻结 ”,并且不会受到对基础表定义的后续更改的影响。例如,如果视图定义为SELECT *在表上定义,则
稍后添加到表中的新列不会成为视图的一部分,从表中删除的列在从视图中选择时会导致错误。
该ALGORITHM子句会影响MySQL处理视图的方式。该DEFINER和
SQL SECURITY子句指定在视图调用时检查访问特权时要使用的安全上下文。该WITH CHECK OPTION子句可用于限制对视图引用的表中的行进行插入或更新。这些条款在本节稍后介绍。
该CREATE VIEW语句需要该CREATE VIEW视图的特权,并且该SELECT语句选择每个列的某些特权
。对于在SELECT声明中其他地方使用的列,您必须具有该SELECT特权。如果该OR REPLACE条款存在,则您还必须拥有DROP该视图的特权。CREATE VIEW也可能需要SUPER权限,具体取决于DEFINER值,如本节后面所述。
当引用视图时,将按照本节后面所述进行特权检查。
一个视图属于一个数据库。默认情况下,默认数据库中会创建一个新视图。要在给定数据库中显式创建视图,请使用db_name.view_name语法来限定视图名称和数据库名称:
CREATE VIEW test.v AS SELECT * FROM t;
SELECT语句中的
非限定表或视图名称
也将相对于默认数据库进行解释。通过使用适当的数据库名称限定表或视图名称,视图可以引用其他数据库中的表或视图。
在数据库中,基表和视图共享相同的名称空间,因此基表和视图不能具有相同的名称。
该SELECT
语句检索的列可以是对表列的简单引用,也可以是使用函数,常量值,运算符等的表达式。
视图必须具有唯一的列名称,而不必重复,就像基表一样。默认情况下,由SELECT语句检索的列的名称用于视图列名称。要为视图列定义显式名称,请将可选column_list子句指定
为逗号分隔标识符列表。名称数量
column_list必须与SELECT语句检索的列数相同
。
视图可以从多种SELECT语句中创建
。它可以引用基表或其他视图。它可以使用连接
UNION,和子查询。该
SELECT甚至不需要引用任何表:
CREATE VIEW v_today(today)AS SELECT CURRENT_DATE;
以下示例定义了一个视图,该视图从另一个表中选择两列以及从这些列中计算出的表达式:
mysql>CREATE TABLE t (qty INT, price INT);mysql>INSERT INTO t VALUES(3, 50);mysql>CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;mysql>SELECT * FROM v;+ ------ + ------- ------- + + | qty | 价格| 值| + ------ + ------- ------- + + | 3 | 50 | 150 | + ------ + ------- ------- + +
视图定义受以下限制:
该SELECT语句不能引用系统变量或用户定义的变量。
在存储的程序中,
SELECT语句不能引用程序参数或局部变量。
该SELECT语句不能引用预准备的语句参数。
定义中提到的任何表格或视图都必须存在。如果在创建视图后删除定义引用的表或视图,则使用视图会导致错误。要检查这种问题的视图定义,请使用该CHECK TABLE语句。
该定义无法引用TEMPORARY
表格,并且您无法创建TEMPORARY
视图。
您无法将触发器与视图相关联。
SELECT语句中的
列名称的别名
将根据64个字符的最大列长度(不是最大别名长度为256个字符)进行检查。
ORDER BY在视图定义中是允许的,但如果使用具有自己的语句从视图中进行选择,它将被忽略ORDER BY。
对于定义中的其他选项或子句,它们被添加到引用视图的语句的选项或子句中,但效果未定义。例如,如果视图定义包含一个LIMIT子句,并且您使用具有其自己的LIMIT子句的语句从视图中进行选择
,则不确定应用了哪个限制。这个道理同样适用于选项,例如
ALL,DISTINCT或者
SQL_SMALL_RESULT后面的
SELECT关键字,并以条款,例如INTO,FOR UPDATE,
LOCK IN SHARE MODE,和
PROCEDURE。
如果通过更改系统变量来更改查询处理环境,则从视图获得的结果可能会受到影响:
MySQL的>CREATE VIEW v (mycol) AS SELECT 'abc';查询OK,0行受影响(0.01秒) MySQL的>SET sql_mode = '';查询OK,0行受影响(0.00秒) MySQL的>SELECT "mycol" FROM v;+ ------- + | mycol | + ------- + | mycol | + ------- + 一排(0.01秒) MySQL的>SET sql_mode = 'ANSI_QUOTES';查询OK,0行受影响(0.00秒) MySQL的>SELECT "mycol" FROM v;+ ------- + | mycol | + ------- + | abc | + ------- + 一排(0.00秒)
当执行引用视图的语句时,
该子句DEFINER和SQL SECURITY子句决定在检查视图的访问权限时使用哪个MySQL帐户。有效的SQL SECURITY
特征值是DEFINER(默认)和INVOKER。这些表明所需的特权必须分别由定义或调用视图的用户持有。
如果user值给出了
DEFINER条款,它应该被指定为MySQL账户
,
或
。缺省
值是执行语句的用户
。这与
明确指定相同。
'user_name'@'host_name'CURRENT_USERCURRENT_USER()DEFINERCREATE VIEWDEFINER = CURRENT_USER
如果该DEFINER条款存在,这些规则将确定有效的DEFINER用户值:
如果您没有SUPER
权限,唯一有效的user
值是您自己的帐户,无论是按字面还是使用指定CURRENT_USER。您无法将定义者设置为某个其他帐户。
如果您有SUPER
权限,则可以指定任何语法上有效的帐户名称。如果该帐户不存在,则会生成警告。
尽管可以使用不存在的DEFINER帐户创建视图,
但如果该SQL SECURITY
值是引用视图,DEFINER但定义者帐户不存在,则会发生错误。
有关视图安全性的更多信息,请参见 第23.6节“存储程序和视图的访问控制”。
在视图定义中,
默认CURRENT_USER返回视图的
DEFINER值。对于使用SQL SECURITY INVOKER特征定义CURRENT_USER的视图,
返回视图调用者的帐户。有关视图内用户审计的信息,请参见第6.3.12节“基于SQL的MySQL账户活动审计”。
在由SQL
SECURITY DEFINER特征定义的存储例程中,
CURRENT_USER返回该例程的
DEFINER值。如果视图定义包含DEFINER值
,则这也会影响在此例程中定义的视图
CURRENT_USER。
MySQL检查像这样的视图特权:
在视图定义时间,视图创建者必须具有使用视图访问的顶级对象所需的特权。例如,如果视图定义引用表列,则创建者必须对定义的选择列表中的每个列具有某种特权,并且SELECT对定义中其他位置使用的每个列都具有
特权。如果定义引用了存储函数,则只能检查调用该函数所需的特权。函数调用时所需的权限只能在执行时进行检查:对于不同的调用,可能会采用函数内的不同执行路径。
当引用视图时DEFINER,将根据视图帐户或调用者持有的权限来检查由视图访问的对象的权限,具体取决于SQL SECURITY
特征是DEFINER或
INVOKER。
如果对视图的引用导致执行存储的函数,则对函数中执行的语句进行特权检查取决于函数SQL SECURITY
特征是DEFINER或
INVOKER。如果安全特征是
DEFINER,则该功能以该DEFINER帐户的特权运行。如果特征是INVOKER,则该功能以由视图SQL
SECURITY特征确定的特权运行。
示例:视图可能取决于存储的函数,该函数可能会调用其他存储的例程。例如,下面的视图调用一个存储函数f():
CREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);
假设f()包含如下的语句:
那么IF名称是NULL CALL p1(); 其他 CALL p2(); 万一;
执行时f()需要检查
执行语句所需的特权
f()。这可能意味着p1()或者需要权限p2(),具体取决于内部的执行路径f()。必须在运行时检查这些权限,并且必须拥有权限的用户由SQL
SECURITY视图v和函数的值确定f()。
在DEFINER和SQL SECURITY
条款的意见是扩展标准SQL。在标准SQL中,视图是按照规则处理的SQL SECURITY
DEFINER。该标准说,视图的定义者与视图模式的所有者相同,在视图上获得适用的特权(例如
SELECT),并可以授予它们。MySQL没有模式“ 所有者 ”的概念,所以MySQL添加了一个条款来标识定义者。该DEFINER
条款是一个扩展,其意图是具有标准的内容; 也就是谁定义视图的永久记录。这就是为什么默认DEFINER值是视图创建者的帐户。
可选ALGORITHM子句是对标准SQL的MySQL扩展。它影响MySQL处理视图的方式。ALGORITHM三个值:
MERGE,TEMPTABLE或
UNDEFINED。有关更多信息,请参见
第23.5.2节“查看处理算法”以及
第8.2.2.3节“优化派生表和视图引用”。
一些视图是可更新的。也就是说,你可以在语句,如使用它们UPDATE,
DELETE或
INSERT更新基础表的内容。为了使视图可以更新,视图中的行与基础表中的行之间必须存在一对一的关系。还有一些其他构造使视图不可更新。
视图中生成的列被认为是可更新的,因为可以将其分配给它。但是,如果这样的列被明确更新,则唯一允许的值是
DEFAULT。有关生成列的信息,请参见第13.1.18.8节“CREATE TABLE和Generated Columns”。
WITH CHECK OPTION可以为可更新视图提供
该子句,以防止插入或更新行,除了那些WHERE子句
select_statement为真的行之外。
在WITH CHECK OPTION可更新视图的子句中LOCAL,CASCADED
关键字和视图按照另一个视图来定义视图的检查范围。的LOCAL
关键字限制CHECK OPTION只向视图限定。CASCADED也会对基础视图的检查进行评估。如果没有给出关键字,则默认为CASCADED。
有关可更新视图和WITH
CHECK OPTION子句的更多信息,请参见
第23.5.3节“可更新和可插入视图”和
第23.5.4节“查看WITH CHECK OPTION子句”。
包含MySQL 5.7.3之前创建的视图会在视图评估时导致错误。考虑这些视图定义,它们与一个序号一起使用:
ORDER BY
integerORDER BY
CREATE VIEW v1 AS SELECT x,y,z FROM t ORDER BY 2; CREATE VIEW v2 AS SELECT x,1,z FROM t ORDER BY 2;
在第一种情况下,ORDER BY 2指的是一个命名列y。在第二种情况下,它引用常量1.对于从任一视图中选择少于2列(ORDER BY
子句中命名的数字)的查询,如果服务器使用MERGE算法评估视图,则会发生错误。例子:
MySQL的>SELECT x FROM v1;错误1054(42S22):'订单子句'中的未知列'2' MySQL的>SELECT x FROM v2;错误1054(42S22):'订单子句'中的未知列'2'
从MySQL 5.7.3开始,为了处理这样的视图定义,服务器将它们以不同的方式写入.frm
存储视图定义的文件中。这种差异是可见的SHOW CREATE VIEW。以前,该.frm文件包含此
ORDER BY 2条款:
对于v1:ORDER BY 2 对于v2:ORDER BY 2
从5.7.3开始,该.frm文件包含以下内容:
对于v1:ORDER BY`t`.`y` 对于v2:ORDER BY''
也就是说v1,2被替换为对所引用列的名称的引用。因为v2,2被一个常量字符串表达式所取代(按常数排序没有效果,所以按任意常量排序都可以)。
如果遇到像刚刚描述的视图评估错误,请删除并重新创建视图,以便该.frm
文件包含更新的视图表示。或者,对于像v2这样的顺序的视图,通过一个常量值,使用no ORDER BY
子句删除并重新创建视图。
DROP {DATABASE | SCHEMA} [如果存在]db_name
DROP DATABASE删除数据库中的所有表并删除数据库。这个声明要
非常小心!要使用
DROP DATABASE,您需要DROP数据库的
特权。
DROP
SCHEMA是一个同义词DROP
DATABASE。
当数据库被删除时,专门为数据库授予的权限不会自动丢弃。它们必须手动放下。请参见第13.7.1.4节“GRANT语法”。
IF EXISTS 用于防止数据库不存在时发生错误。
如果删除了默认数据库,则默认数据库未设置(DATABASE()函数返回
NULL)。
如果您DROP DATABASE在符号链接的数据库上使用,则链接和原始数据库都将被删除。
DROP DATABASE返回已删除的表的数量。这与.frm删除的文件数量相对应
。
该DROP DATABASE语句从给定的数据库目录中删除MySQL自身在正常操作期间可能创建的文件和目录:
所有文件具有以下扩展名:
.BAK
.DAT
.HSH
.MRG
.MYD
.MYI
.TRG
.TRN
.cfg
.db
.frm
.ibd
.ndb
.par
该db.opt文件,如果存在。
如果在MySQL删除刚刚列出的文件或目录后,其他文件或目录仍保留在数据库目录中,则无法删除数据库目录。在这种情况下,您必须手动删除任何剩余的文件或目录并DROP DATABASE再次发出该
语句。
删除数据库不会删除TEMPORARY在该数据库中创建的任何
表。TEMPORARY当创建它们的会话结束时,表格会自动删除。请参见
第13.1.18.3节“CREATE TEMPORARY TABLE语法”。
您也可以使用mysqladmin删除数据库。请参见第4.5.2节“ mysqladmin - 管理MySQL服务器的客户端”。
DROP EVENT [如果存在] event_name
该声明将删除名为的事件
event_name。该事件立即停止激活,并从服务器上完全删除。
如果事件不存在,则会产生错误ERROR 1517(HY000):未知事件' event_name'。您可以覆盖它并使该语句生成不存在的事件的警告,而不是使用IF EXISTS。
此语句需要EVENT
特权才能放入事件。
该DROP FUNCTION语句用于删除存储的函数和用户定义的函数(UDF):
有关删除存储函数的信息,请参见 第13.1.27节“DROP PROCEDURE和DROP FUNCTION语法”。
有关丢弃用户定义函数的信息,请参见 第13.7.3.2节“DROP FUNCTION语法”。
DROP INDEXindex_nameONtbl_name[algorithm_option|lock_option] ...algorithm_option: 算法[=] {默认|输入|复制}lock_option: LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}
DROP INDEX删除index_name表中
指定的索引
tbl_name。该语句映射到一个ALTER TABLE语句以删除索引。请参见第13.1.8节“ALTER TABLE语法”。
要删除主键,索引名称始终
PRIMARY是必须指定为带引号的标识符,因为PRIMARY它是保留字:
DROP INDEX`PRIMARY` ON t;
可变宽度列的索引
NDB在线丢弃; 即没有任何表格复制。虽然在操作期间锁定在同一 API节点上的其他操作,但该表并未锁定为禁止从其他NDB集群API节点访问。只要服务器确定可以这样做,它就会自动完成; 您不必使用任何特殊的SQL语法或服务器选项来使其发生。
ALGORITHM并且LOCK可能会给出子句来影响表的复制方法以及在修改索引时读取和写入表的并发性级别。它们与该ALTER TABLE陈述具有相同的含义
。有关更多信息,请参见第13.1.8节“ALTER TABLE语法”
NDB集群以前DROP
INDEX使用ONLINE和
OFFLINE关键字支持在线操作。MySQL NDB Cluster 7.5及更高版本不再支持这些关键字,它们的使用会导致语法错误。相反,MySQL NDB Cluster 7.5和更高版本支持ALGORITHM=INPLACE使用与标准MySQL服务器相同语法的在线操作
。有关更多信息,请参见第13.1.8.2节“NDB集群中的ALTER TABLE联机操作”。
DROP LOGFILE GROUPlogfile_groupENGINE [=]engine_name
该语句将删除名为的日志文件组
logfile_group。日志文件组必须已经存在或出现错误。(有关创建日志文件组的信息,请参见第13.1.15节“CREATE LOGFILE GROUP语法”。)
在删除日志文件组之前,您必须删除使用该日志文件组进行UNDO
日志记录的所有表空间。
必需的ENGINE子句提供了待删除的日志文件组使用的存储引擎的名称。目前,唯一允许的值
engine_name是
NDBand
NDBCLUSTER。
DROP LOGFILE GROUP仅适用于NDB群集的磁盘数据存储。请参见
第21.5.13节“NDB群集磁盘数据表”。
DROP {程序| FUNCTION} [如果存在]sp_name
该语句用于删除存储过程或函数。也就是说,指定的例程将从服务器中删除。你必须有ALTER ROUTINE
例行的特权。(如果automatic_sp_privileges启用了
系统变量,那么该特权EXECUTE
将在创建例程时自动授予例程创建者,并在例程被删除时从创建者删除。请参见第23.2.2节“存储例程和MySQL特权”。)
该IF EXISTS子句是一个MySQL扩展。它可以防止过程或函数不存在时发生错误。产生一个警告,可以用来查看
SHOW WARNINGS。
DROP FUNCTION也用于删除用户定义的函数(请参见第13.7.3.2节“DROP FUNCTION语法”)。
DROP SERVER [如果存在] server_name
删除名为的服务器的服务器定义
。server_namemysql.servers表格中的相应行被删除。该声明需要
SUPER特权。
删除表的服务器不会影响FEDERATED创建时使用此连接信息的任何
表。请参见
第13.1.17节“CREATE SERVER语法”。
DROP SERVER导致隐式提交。请参见
第13.3.3节“导致隐式提交的语句”。
DROP SERVER 不写入二进制日志,不管正在使用的日志格式如何。
DROP [TEMPORARY] TABLE [IF EXISTS]
tbl_name[,tbl_name] ...
[RESTRICT | 级联]
DROP TABLE删除一个或多个表。您必须拥有DROP
每个表的特权。
请小心这个声明!它删除表格定义和所有表格数据。对于分区表,它将永久删除表定义,其所有分区以及存储在这些分区中的所有数据。它还删除与删除表关联的分区定义。
DROP TABLE会导致隐式提交,除非与TEMPORARY
关键字一起使用。请参见第13.3.3节“导致隐式提交的语句”。
删除表时,专门为该表授予的权限不会自动删除。它们必须手动放下。请参见第13.7.1.4节“GRANT语法”。
如果参数列表中的任何表不存在,则该语句返回一个错误,指出其名称不能删除的不存在的表,但会删除列表中存在的所有表。
使用IF EXISTS以防止发生错误,从该表不存在发生。而不是一个错误,
NOTE为每个不存在的表生成一个; 这些笔记可以用来显示SHOW
WARNINGS。请参见第13.7.5.40节“SHOW WARNINGS Syntax”。
IF EXISTS在存在.frm文件但不存在由存储引擎管理的表的特殊情况下,也可以用于删除表
。(例如,如果从存储引擎中删除表之后但.frm删除文件之前发生异常服务器退出
。)
该TEMPORARY关键字具有以下作用:
该声明仅删除TEMPORARY表格。
该声明不会导致隐式提交。
没有访问权限被检查。一张TEMPORARY
表只有创建它的会话才可见,所以不需要检查。
使用TEMPORARY是确保您不会意外删除非TEMPORARY
表的一种好方法。
在RESTRICT和CASCADE
关键字无能为力。他们被允许从其他数据库系统移植。
DROP TABLE不支持所有innodb_force_recovery
设置。请参见第14.21.2节“强制InnoDB恢复”。
DROP TABLESPACEtablespace_name[引擎[=]engine_name]
该语句删除以前使用的表空间CREATE TABLESPACE。它支持所有MySQL NDB Cluster 7.5版本,并且
InnoDB在标准的MySQL服务器中也是如此。
ENGINE设置使用表空间的存储引擎,其中engine_name是存储引擎的名称。目前,值
InnoDB和NDB支持。如果未设置,default_storage_engine则使用该值
。如果它与用于创建表空间的存储引擎不同,则该DROP TABLESPACE语句失败。
对于InnoDB表空间,在DROP
TABLESPACE操作之前必须从表空间中删除所有表。如果表空间不为空,则
DROP TABLESPACE返回错误。
与InnoDB系统表空间一样,截断或删除InnoDB存储在常规表空间中的表可在表空间.ibd数据文件中创建空闲空间,该
数据文件只能用于新InnoDB数据。通过这种操作,空间不会被释放回操作系统,就像每个表文件的表空间一样。
NDB要删除
的表空间不得包含任何数据文件; 换句话说,在你可以删除一个
NDB表空间之前,你必须首先使用它来删除它的每个数据文件
ALTER TABLESPACE
... DROP DATAFILE。
表空间不会自动删除。表空间必须明确地使用DROP
TABLESPACE。DROP
DATABASE在这方面没有效果,即使该操作会删除属于表空间的所有表。
一个DROP DATABASE操作可以丢弃属于一般的表空间的表,但它不能删除表空间,即使操作下降属于表空间中的所有表。表空间必须使用显式删除。
DROP TABLESPACE
tablespace_name
与系统表空间类似,截断或删除存储在通用表空间中的表可在通用表空间.ibd数据文件的内部创建空闲空间,该
数据文件只能用于新InnoDB数据。空间不会释放回操作系统,因为它是用于每个表文件的表空间。
这个例子演示了如何删除一个InnoDB
通用的表空间。常规表空间ts1
是使用单个表创建的。在删除表空间之前,必须删除表。
mysql>CREATE TABLESPACE `ts1`- >ADD DATAFILE 'ts1.ibd'- >ENGINE=INNODB;查询OK,0行受影响(0.01秒) mysql>CREATE TABLE t1 (c1 INT PRIMARY KEY)- >TABLESPACE ts10- >ENGINE=INNODB;查询OK,0行受影响(0.02秒) MySQL的>DROP TABLE t1;查询OK,0行受影响(0.01秒) MySQL的>DROP TABLESPACE ts1;查询OK,0行受影响(0.01秒)
这个例子展示了如何删除一个NDB
表myts具有命名的数据文件
mydata-1.dat之后首先创建表,并假定命名一个日志文件组的存在
mylg(见
章节13.1.15,“CREATE LOGFILE GROUP语法”)。
mysql>CREATE TABLESPACE myts- >ADD DATAFILE 'mydata-1.dat'- >USE LOGFILE GROUP mylg- >ENGINE=NDB;
ALTER TABLESPACE如下所示,
您必须使用(如下所示)删除表空间中的所有数据文件
,然后才能将其删除:
mysql>ALTER TABLESPACE myts- >DROP DATAFILE 'mydata-1.dat'- >ENGINE=NDB;MySQL的>DROP TABLESPACE myts;
DROP TRIGGER [如果存在] [schema_name。]trigger_name
这个声明放下一个触发器。模式(数据库)名称是可选的。如果架构被省略,则触发器将从默认架构中删除。DROP TRIGGER
需要TRIGGER与触发器关联的表的特权。
使用IF EXISTS以防止发生错误,从一个不存在的触发器发生。A
NOTE在使用时为不存在的触发器生成IF EXISTS。请参见
第13.7.5.40节“SHOW WARNINGS Syntax”。
如果删除表格,也会删除表格的触发器。
DROP VIEW [如果存在]
view_name[,view_name ] ...
[RESTRICT | 级联]
DROP VIEW删除一个或多个视图。您必须拥有DROP
每个视图的特权。
如果任何在参数列表中命名的视图不存在,则该语句将返回一个错误,指出它不能删除的不存在的视图的名称,但也会删除列表中存在的所有视图。
在MySQL 8.0中,DROP VIEW
如果在参数列表中命名的视图不存在,则失败。由于行为的变化,DROP VIEW当MySQL 5.7主节点复制到MySQL 8.0从节点时,部分完成的
操作失败。为避免此故障情形,请IF EXISTS在DROP
VIEW语句中使用
语法来防止不存在的视图发生错误。有关更多信息,请参阅
原子数据定义语句支持。
该IF EXISTS子句可防止不存在的视图发生错误。当给出这个子句时,
NOTE为每个不存在的视图生成一个。请参见第13.7.5.40节“SHOW WARNINGS Syntax”。
RESTRICT并且CASCADE,如果给出,则被解析并忽略。
RENAME TABLE
tbl_nameTO new_tbl_name
[,tbl_name2TO new_tbl_name2] ...
RENAME TABLE重命名一个或多个表。您必须具有ALTER与
DROP原始表的权限,以及CREATE与
INSERT新表的权限。
例如,要重命名名为old_table
to 的表new_table,请使用以下语句:
RENAME TABLE old_table TO new_table;
该声明相当于以下
ALTER TABLE声明:
ALTER TABLE old_table RENAME new_table;
RENAME TABLE不同的是ALTER
TABLE,可以在一个语句中重命名多个表:
RENAME TABLE old_table1 TO new_table1,
old_table2到new_table2,
old_table3至new_table3;
重命名操作从左到右执行。因此,要交换两个表名,请执行此操作(假定具有中间名的表tmp_table尚不存在):
RENAME TABLE old_table to tmp_table,
new_table TO old_table,
tmp_table TO new_table;
执行时RENAME TABLE,不能有任何锁定的表或活动事务。在满足该条件的情况下,重命名操作是自动完成的; 重命名过程中没有其他会话可以访问任何表。
如果在a过程中发生任何错误RENAME TABLE,则说明失败并且不做任何更改。
您可以使用RENAME TABLE将表从一个数据库移动到另一个数据库:
重命名表current_db.tbl_nameTOother_db.tbl_name;
使用这种方法将所有表从一个数据库移动到另一个数据库实际上会重命名数据库(MySQL没有单一语句的操作),只是原始数据库仍然存在,尽管没有表。
就像RENAME TABLE,ALTER TABLE ...
RENAME也可以用来将表格移动到不同的数据库。无论使用何种语句,如果重命名操作会将表移动到位于不同文件系统上的数据库,则结果的成功与平台相关,并取决于用于移动表文件的底层操作系统调用。
如果表具有触发器,则尝试将该表重命名为其他数据库会失败,并显示错误的模式错误中的触发器。
RENAME TABLE不适用于
TEMPORARY表格。但是,您可以使用
ALTER TABLE重命名
TEMPORARY表。
RENAME TABLE 适用于视图,但不能将视图重命名为不同的数据库。
专门为重命名的表或视图授予的任何权限都不会迁移到新名称。他们必须手动更改。
RENAME TABLE更改内部生成的外键约束名称和包含字符串“ tbl_name_ibfk_ ”以反映新表名称的用户定义外键约束名称
。InnoDB将包含字符串“ tbl_name_ibfk_ ”的外键约束名称解释
为内部生成的名称。
除非有冲突,否则指向重命名表的外键约束名称会自动更新,在这种情况下,语句会失败并显示错误。如果重命名的约束名称已存在,则会发生冲突。在这种情况下,您必须删除并重新创建外键才能正常工作。
TRUNCATE [TABLE] tbl_name
TRUNCATE TABLE完全清空一张桌子。它需要DROP
特权。
从逻辑上讲,TRUNCATE TABLE类似于一个DELETE一个删除所有行,或序列声明DROP
TABLE和CREATE TABLE
陈述。为了实现高性能,它绕过了删除数据的DML方法。因此,它不能被回滚,它不会导致ON DELETE触发器触发,并且不能对InnoDB具有父子外键关系的表执行。
虽然TRUNCATE TABLE类似DELETE,但它被归类为DDL语句而不是DML语句。它与DELETE以下方面有所不同
:
截断操作将删除并重新创建表,这比逐个删除行要快得多,特别是对于大型表。
截断操作会导致隐式提交,因此无法回滚。请参见第13.3.3节“导致隐式提交的语句”。
如果会话持有活动表锁,则无法执行截断操作。
TRUNCATE TABLE如果来自引用该表的其他表存在任何约束,则会
失败
InnoDB表或
表。允许同一个表的列之间的外键约束。
NDBFOREIGN KEY
截断操作不会为已删除的行数返回有意义的值。通常的结果是“ 0行受到影响 ”,应解释为“ 无信息。”
只要表格格式文件
有效tbl_name.frmTRUNCATE TABLE,即使数据或索引文件已损坏,表格也可以重新创建为空表格
。
任何AUTO_INCREMENT值都将重置为其起始值。即使对于MyISAM
和InnoDB,通常也不会重用序列值。
与分区表一起使用时,
TRUNCATE TABLE保留分区; 也就是说,数据和索引文件被删除并重新创建,而分区定义(.par)文件不受影响。
该TRUNCATE TABLE语句不调用ON DELETE触发器。
TRUNCATE TABLE对于一个表来说,关闭所有打开的表的处理程序
HANDLER OPEN。
TRUNCATE TABLE被视为用于二进制日志记录和复制的目的,
DROP TABLE其次是
CREATE TABLE- 作为DDL而不是DML。这是因为InnoDB,在事务隔离级别不允许基于语句的日志记录(READ
COMMITTED或READ
UNCOMMITTED)使用
和其他事务性存储引擎时,该语句在使用STATEMENT或
MIXED日志记录模式下未被记录和复制。(错误#36763)但是,它仍以InnoDB前面所述的方式应用于复制从站
。
在具有大InnoDB缓冲池并且已
innodb_adaptive_hash_index
启用的TRUNCATE TABLE系统上,由于移除InnoDB表的自适应散列索引条目时发生LRU扫描,操作可能会导致系统性能暂时下降。这个问题
DROP TABLE在MySQL 5.5.23(Bug#13704145,Bug#64284)中得到解决,但仍然是一个已知问题
TRUNCATE TABLE(错误#68184)。
TRUNCATE TABLE可以与性能架构汇总表一起使用,但效果是将汇总列重置为0或NULL不删除行。请参见第25.11.15节“性能模式摘要表”。
CALLsp_name([parameter[,...]]) CALLsp_name[()]
该CALL语句调用之前定义的存储过程
CREATE PROCEDURE。
没有参数的存储过程可以在没有括号的情况下调用。也就是说,CALL p()而且
CALL p是等价的。
CALL可以通过使用回被声明为参数值到它的调用者
OUT或INOUT参数。当过程返回时,客户端程序还可以获取在例程中执行的最终语句所影响的行数:在SQL级别,调用该
ROW_COUNT()函数; 从C API调用该
mysql_affected_rows()函数。
要使用OUT或INOUT参数从过程中获取值
,请通过用户变量传递参数,然后在过程返回后检查变量的值。(如果从另一个存储过程或函数内调用该过程,则还可以将例程参数或本地例程变量作为
参数IN或INOUT参数INOUT传递)。对于参数,在将其传递给过程之前对其进行初始化。以下过程具有OUT该过程设置为当前服务器版本的
INOUT参数以及该过程从当前值增加1的值:
CREATE PROCEDURE p(OUT ver_param VARCHAR(25),INOUT incr_param INT) 开始 #设置OUT参数的值 SELECT VERSION()INTO ver_param; #增加INOUT参数的值 SET incr_param = incr_param + 1; 结束;
在调用过程之前,初始化要作为INOUT参数传递的变量。调用该过程后,两个变量的值将被设置或修改:
mysql>SET @increment = 10;mysql>CALL p(@version, @increment);mysql>SELECT @version, @increment;+ ------------------ + ------------ + | @version | @increment | + ------------------ + ------------ + | 5.7.20-debug-log | 11 | + ------------------ + ------------ +
在和
CALL使用的准备语句中,占位符可用于参数和
参数。这些类型的参数可以使用如下:
PREPAREEXECUTEINOUTINOUT
mysql>SET @increment = 10;mysql>PREPARE s FROM 'CALL p(?, ?)';mysql>EXECUTE s USING @version, @increment;mysql>SELECT @version, @increment;+ ------------------ + ------------ + | @version | @increment | + ------------------ + ------------ + | 5.7.20-debug-log | 11 | + ------------------ + ------------ +
要编写使用CALLSQL语句执行产生结果集的存储过程的C程序,
CLIENT_MULTI_RESULTS必须启用该
标志。这是因为CALL除了过程中执行的语句可能返回的任何结果集外,每个结果都会返回一个结果来指示调用状态。CLIENT_MULTI_RESULTS如果CALL用于执行包含预处理语句的任何存储过程,则还必须启用它们。无论何时加载这样的过程,无论这些陈述是否会生成结果集都不能确定,所以有必要假定它们将会。
CLIENT_MULTI_RESULTS可以在你打电话时启用mysql_real_connect(),或者明确地通过传递CLIENT_MULTI_RESULTS
标志本身,或者通过传递CLIENT_MULTI_STATEMENTS(也启用CLIENT_MULTI_RESULTS)隐式地
启用
。
CLIENT_MULTI_RESULTS是默认启用的。
要处理CALL
使用mysql_query()or
执行的语句
的结果mysql_real_query(),请使用调用的循环mysql_next_result()来确定是否有更多结果。有关示例,请参见
第27.8.16节“C API多语句执行支持”。
C程序可以使用prepared-statement接口来执行
CALL语句和访问
OUT以及INOUT参数。这是通过CALL使用调用mysql_stmt_next_result()来确定是否有更多结果的循环来处理语句的结果来完成的
。有关示例,请参见
第27.8.18节“C API准备的CALL语句支持”。提供MySQL接口的语言可以使用预准备
CALL语句直接检索OUT和INOUT
过程参数。
对存储程序引用的对象进行元数据更改会被检测到,并会在下次执行程序时自动重新分析受影响的语句。有关更多信息,请参见 第8.10.4节“准备好的语句和存储的程序的缓存”。
DELETE 是从表中删除行的DML语句。
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROMtbl_name[PARTITION(partition_name[,partition_name] ...)] [哪里where_condition] [ORDER BY ...] [限制row_count]
该DELETE语句从中删除行
tbl_name并返回已删除行的数量。要检查已删除行的数量,请调用
第12.14节“信息函数”中ROW_COUNT()所述的
函数。
可选WHERE条款中的条件确定要删除哪些行。没有WHERE
子句时,所有行都被删除。
where_condition是一个表达式,对于要删除的每一行,其计算结果为true。它按照第13.2.9节“SELECT语法”中的说明进行指定。
如果ORDER BY指定了子句,则按指定的顺序删除行。该
LIMIT子句限制了可以删除的行数。这些条款适用于单表删除,但不适用于多表删除。
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
tbl_name[。*] [,tbl_name[。*]] ...
FROM table_references
[WHERE where_condition]
删除[LOW_PRIORITY] [QUICK] [IGNORE]
FROM tbl_name[。*] [,tbl_name[。*]] ...
使用table_references
[WHERE where_condition]
您需要DELETE表上的特权才能从中删除行。您只需要SELECT任何只读的列的
特权,例如在
WHERE子句中指定的列。
当您不需要知道已删除行的数量时,与不带子句TRUNCATE TABLE的DELETE语句
相比,该
语句是清空表的更快方法
WHERE。与之不同
DELETE,
TRUNCATE TABLE不能在交易中使用,或者如果您在表格上有锁定。请参见
第13.1.34节“TRUNCATE TABLE语法”和
第13.3.5节“LOCK TABLES和UNLOCK TABLES Syntax”。
删除操作的速度也可能受到第8.2.4.3节“优化删除语句”中讨论的因素的影响。
为了确保给定的DELETE
语句不会花费太多时间,MySQL特定的
子句用于指定要删除的最大行数。如果要删除的行数大于限制,请重复该
语句,直到受影响的行数小于该值。
LIMIT row_countDELETEDELETELIMIT
您无法从表中删除并从子查询中的同一个表中进行选择。
DELETE支持使用该PARTITION选项的显式分区选择,该选项采用从中选择要删除的行的一个或多个分区或子分区(或两者)的逗号分隔名称列表。未包含在列表中的分区将被忽略。给定一个t带有分区名称
的分区表p0,执行该语句DELETE
FROM t PARTITION (p0)对表执行操作具有相同的效果ALTER
TABLE t TRUNCATE PARTITION (p0); 在这两种情况下,分区p0中的所有行都被删除。
PARTITION可以与WHERE条件一起使用
,在这种情况下,仅在列出的分区中的行上测试条件。例如,
DELETE FROM t PARTITION (p0) WHERE c < 5
仅从p0条件c < 5为真的分区中删除行; 任何其他分区中的行都不会被检查,因此不会受到
DELETE。
该PARTITION选项也可以用于多表DELETE语句。您最多可以在该FROM选项中命名的每个表格使用一个这样的
选项。
有关更多信息和示例,请参见 第22.5节“分区选择”。
如果删除包含AUTO_INCREMENT列最大值的行
,则该值不会重用于
表MyISAM或InnoDB表。如果在模式中删除表中的所有行(没有
子句)
,则序列将重新开始,除了和以外的所有存储引擎
。对于
表的这种行为有一些例外,如
第14.8.1.5节“InnoDB中的AUTO_INCREMENT处理”所述。
DELETE
FROM tbl_nameWHEREautocommitInnoDBMyISAMInnoDB
对于MyISAM表格,您可以AUTO_INCREMENT在多列键中指定
辅助列。在这种情况下,即使对于MyISAM
表格,也会重复使用从序列顶部删除的值。参见第3.6.9节“使用AUTO_INCREMENT”。
该DELETE语句支持以下修饰符:
如果指定LOW_PRIORITY,服务器会延迟执行,DELETE
直到没有其他客户端正在从表中读取数据。这会影响只使用表级锁只存储引擎(例如MyISAM,MEMORY和MERGE)。
对于MyISAM表,如果使用
QUICK修饰符,则存储引擎在删除过程中不合并索引树叶,这可能会加速某些类型的删除操作。
该IGNORE修改导致MySQL删除行的过程中忽略的错误。(在解析阶段遇到的错误以通常的方式进行处理。)由于使用而IGNORE被忽略的错误
将作为警告返回。有关更多信息,请参阅IGNORE关键字和严格SQL模式的比较。
如果DELETE语句包含一个
ORDER BY子句,则按照该子句指定的顺序删除行。这主要与结合使用LIMIT。例如,以下语句查找与该WHERE子句匹配的行,按照它们进行排序timestamp_column,并删除第一个(最老的)行:
DELETE FROM somelog WHERE user ='jcole' ORDER BY timestamp_column LIMIT 1;
ORDER BY 也有助于按照避免参照完整性违规的顺序删除行。
如果从大表中删除多行,则可能会超出表的锁表大小InnoDB。为了避免这个问题,或者只是为了尽量减少表保持锁定的时间,以下策略(根本不使用
DELETE)可能会有所帮助:
选择不要删除的行到与原始表具有相同结构的空表中:
INSERT INTO t_copy SELECT * FROM t WHERE ...;
使用RENAME TABLE以原子移动原始表的方式进行,并重新命名拷贝到原来的名称:
RENAME TABLE t to t_old,t_copy TO t;
放下原来的桌子:
DROP TABLE t_old;
执行时没有其他会话可以访问涉及的表
RENAME TABLE,因此重命名操作不受并发性问题的影响。请参见
第13.1.33节“RENAME TABLE语法”。
在MyISAM表格中,删除的行保留在链接列表中,随后的
INSERT操作重用旧的行位置。要回收未使用的空间并减小文件大小,请使用该
OPTIMIZE TABLE语句或
myisamchk实用程序重新组织表。
OPTIMIZE TABLE更容易使用,但myisamchk更快。请参见
第13.7.2.4节“OPTIMIZE TABLE语法”和第4.6.3节“ myisamchk - MyISAM表维护实用程序”。
该QUICK修改会影响指数的叶子是否合并的删除操作。DELETE QUICK
对于删除行的索引值被稍后插入的行中的相似索引值替换的应用程序最为有用。在这种情况下,重新使用已删除值留下的孔。
DELETE QUICK在删除的值导致索引块填充不足的索引块跨越一系列索引值并且新的插入再次发生时无用。在这种情况下,使用
QUICK可能会导致索引中浪费的空间保持未复原状态。以下是这种情况的一个例子:
在这种情况下,与删除的索引值关联的索引块会变成未充满,但由于使用而不会与其他索引块合并QUICK。新插入发生时,它们仍然未充满,因为新行在已删除的范围中没有索引值。此外,即使您以后DELETE没有
使用它们,它们仍然未充满
QUICK,除非某些已删除的索引值恰好位于未充满块内或附近的索引块中。要在这些情况下回收未使用的索引空间,请使用OPTIMIZE TABLE。
如果您要删除表中的许多行,则使用DELETE QUICK后面的操作
可能会更快OPTIMIZE TABLE。这会重建索引而不是执行许多索引块合并操作。
您可以在DELETE语句中指定多个表以
从一个或多个表中删除行,具体取决于WHERE子句中的条件
。你不能使用ORDER
BY或LIMIT在多个表中
DELETE。该
table_references子句列出了连接中涉及的表,如
第13.2.9.2节“JOIN语法”中所述。
对于第一个多表语法,只FROM删除子句前列出的表中匹配的行。对于第二个多表语法,只删除FROM该USING子句中列出的表(该子句之前)中的匹配行。其效果是,您可以同时从多个表中删除行,并具有仅用于搜索的附加表:
DELETE t1,t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id = t2.id AND t2.id = t3.id;
要么:
从t1,t2中删除使用t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id = t2.id AND t2.id = t3.id;
这些语句在搜索要删除的行时使用全部三个表,但仅从表t1和删除匹配的行
t2。
前面的示例使用INNER JOIN,但多表DELETE语句可以使用语句中允许的其他类型的连接
SELECT,例如
LEFT JOIN。例如,要删除那些t1不匹配的行
t2,请使用LEFT JOIN:
DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id = t2.id WHERE t2.id IS NULL;
为了与Access兼容,
.*每个
语法都允许使用该语法。
tbl_name
如果您使用DELETE
涉及InnoDB存在外键约束的表的多表语句,则MySQL优化器可能会按照与其父/子关系不同的顺序来处理表。在这种情况下,语句失败并回滚。相反,您应该从单个表中删除并依赖提供的ON DELETE功能
InnoDB来相应地修改其他表。
如果您为表格声明别名,则在引用表格时必须使用别名:
DELETE t1 FROM test AS t1,test2 WHERE ...
多表中的表别名
DELETE应仅在table_references语句部分中声明。在其他地方,允许别名引用,但不允许别名声明。
正确:
DELETE a1,a2 FROM t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id = a2.id; 删除a1,a2使用t1作为a1内部联接t2 AS a2 WHERE a1.id = a2.id;
不正确:
DELETE t1 AS a1,t2 AS a2 FROM t1 INNER JOIN t2 WHERE a1.id = a2.id; 从t1中删除as a1,t2 as a2使用t1 INNER JOIN t2 WHERE a1.id = a2.id;
DOexpr[,expr] ...
DO执行表达式但不返回任何结果。在大多数方面,
DO都是速记,但有一个好处,就是当你不关心结果时,速度会稍微快一点。
SELECT
expr, ...
DO主要用于有副作用的功能,例如
RELEASE_LOCK()。
例子:这个SELECT语句暂停,但也产生一个结果集:
MySQL的> SELECT SLEEP(5);
+ ---------- +
| 睡眠(5)|
+ ---------- +
| 0 |
+ ---------- +
一排(5.02秒)
DO另一方面,暂停而不产生结果集。
MySQL的> DO SLEEP(5);
查询OK,0行受影响(4.99秒)
这可能是有用的,例如在存储函数或触发器中,这会禁止生成结果集的语句。
DO只执行表达式。它不能用于所有SELECT可以使用的情况。例如,DO id FROM t1它是无效的,因为它引用了一个表。
HANDLERtbl_nameOPEN [[AS]alias] HANDLERtbl_nameREADindex_name{= | <= | > = | <| >}(value1,value2,...) [哪里where_condition] [限制...] 处理器tbl_name阅读index_name{FIRST | 下一页| 上一页| LAST} [哪里where_condition] [限制...] HANDLERtbl_nameREAD {FIRST | 下一个 } [哪里where_condition] [限制...] 手柄tbl_name关闭
该HANDLER语句提供对表存储引擎接口的直接访问。它可用于
InnoDB和MyISAM表格。
该HANDLER ... OPEN声明打开一张表格,使其能够使用随后的HANDLER ...
READ声明进行访问。该表格对象不被其他会话共享,并且在会话呼叫HANDLER ... CLOSE或会话终止之前不会关闭
。
如果使用别名打开表,则使用其他HANDLER语句进一步引用打开的表必须使用别名而不是表名。如果您不使用别名,但使用数据库名称限定的表名打开该表,则其他引用必须使用非限定表名。例如,对于打开使用的表格
mydb.mytable,必须使用更多参考
mytable。
第一种HANDLER ... READ语法获取一行,其中指定的索引满足给定值并满足
WHERE条件。如果您有多列索引,请将索引列值指定为逗号分隔列表。指定索引中所有列的值,或者为索引列的最左边前缀指定值。假设一个索引my_idx包括三个名为列col_a,
col_b以及col_c以该顺序。该HANDLER语句可以为索引中的所有三列指定值,也可以为最左边的前缀中的列指定值。例如:
HANDLER ... READ my_idx =(col_a_val,col_b_val,col_c_val)... HANDLER ... READ my_idx =(col_a_val,col_b_val)... HANDLER ... READ my_idx =(col_a_val)...
要使用HANDLER接口来引用表PRIMARY KEY,请使用带引号的标识符
`PRIMARY`:
HANDLER tbl_nameREAD'PRIMARY` ...
第二种HANDLER ... READ语法按照与WHERE条件匹配的索引顺序从表中提取一行
。
第三种HANDLER ... READ语法按照与WHERE条件匹配的自然行顺序从表中提取一行
。它比希望全表扫描更快
。自然行顺序是行存储在表数据文件中的顺序。这个声明也适用于表格,但是没有这样的概念,因为没有单独的数据文件。
HANDLER tbl_name READ
index_nameMyISAMInnoDB
没有LIMIT子句,所有形式的
HANDLER ... READ获取单行(如果有)。要返回特定数量的行,请包含一个
LIMIT子句。它与语句的语法相同
SELECT。请参见
第13.2.9节“SELECT语法”。
HANDLER ... CLOSE关闭一张已打开的表格HANDLER ... OPEN。
使用HANDLER
接口而不是普通SELECT
语句有几个原因:
HANDLER快于
SELECT:
HANDLER使它更容易移植到使用低级别ISAM接口的MySQL应用程序。(有关调整使用键值存储范例的应用程序的其他方法,请参见第14.20节“InnoDB memcached插件”。)
HANDLER使您能够以难以(甚至不可能)完成的方式遍历数据库SELECT。在
HANDLER使用向数据库提供交互式用户界面的应用程序时,界面是更自然地查看数据的方式。
HANDLER是一个有点低级的陈述。例如,它不提供一致性。也就是说,
HANDLER ... OPEN它不
走表的快照,并不能
锁定表。这意味着在HANDLER ...
OPEN发布语句之后,可以修改表格数据(通过当前会话或其他会话),并且这些修改可能只是部分可见HANDLER ...
NEXT或HANDLER ... PREV扫描。
打开的处理程序可以关闭并标记为重新打开,在这种情况下,处理程序会丢失其在表格中的位置。当以下两种情况都属实时会发生这种情况:
任何会话FLUSH
TABLES在处理程序的表上执行或DDL语句。
处理程序打开的会话将执行HANDLER使用表的非语句。
TRUNCATE TABLE对于一个表来说,关闭所有打开的表的处理程序
HANDLER OPEN。
如果一个表被刷新并且
被打开,处理程序会被隐式刷新并丢失其位置。
FLUSH
TABLES tbl_name WITH READ
LOCKHANDLER
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION(partition_name[,partition_name] ...)]
[(col_name[,col_name] ...)]
{VALUES | VALUE}(value_list)[,(value_list)] ...
[在重复密钥更新assignment_list]
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION(partition_name[,partition_name] ...)]
SET assignment_list
[在重复密钥更新assignment_list]
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION(partition_name[,partition_name] ...)]
[(col_name[,col_name] ...)]
选择 ...
[在重复密钥更新assignment_list]
value:
{ expr| 默认}
value_list:
value[,value] ...
assignment:
col_name=value
assignment_list:
assignment[,assignment] ...
INSERT将新行插入到现有表中。该INSERT
... VALUES和
INSERT ... SET
语句的形式插入基于明确指定的值的行。的INSERT
... SELECT形式插入从另一个或多个表中选择行。INSERT使用
ON DUPLICATE KEY UPDATE子句可以使现有行更新,如果要插入的行将导致UNIQUE索引中的重复值或PRIMARY
KEY。
有关更多信息
INSERT ...
SELECT,并
INSERT ... ON
DUPLICATE KEY UPDATE请参见
第13.2.5.1,“INSERT ... SELECT语法”和
第13.2.5.2,“插入...对重复密钥更新语法”。
在MySQL 5.7中,DELAYED关键字被接受但被服务器忽略。出于这个原因,请参见第13.2.5.3节“INSERT DELAYED语法”,
插入表格需要表格的
INSERT特权。如果使用ON DUPLICATE KEY UPDATE子句并且重复键导致UPDATE执行,则语句需要UPDATE更新列的
权限。对于已读但未修改的列,只需要SELECT特权(例如仅在
子句中的col_name= expr
赋值的右侧引用的列
ON DUPLICATE KEY UPDATE)。
当插入到分区表中时,可以控制哪些分区和子分区接受新行。该
PARTITION选项采用表格的一个或多个分区或子分区(或两者)的逗号分隔名称列表。如果由给定INSERT语句插入的任何行与列出的其中一个分区不匹配,则
INSERT语句失败,并显示错误发现行不匹配给定分区集。有关更多信息和示例,请参见
第22.5节“分区选择”。
您可以使用REPLACE而不是
INSERT覆盖旧的行。
REPLACE是INSERT IGNORE处理包含复制旧行的唯一键值的新行的对应部分
:新行替换旧行而不是丢弃。请参见第13.2.8节“REPLACE语法”。
tbl_name是应插入行的表。指定语句为其提供值的列,如下所示:
在表名后面提供逗号分隔列名称的带括号的列表。在这种情况下,每个命名列的值必须由VALUES列表或SELECT语句提供。
如果您未为INSERT ...
VALUESor
指定列名称列表,
INSERT ...
SELECT则必须由VALUES列表或
SELECT语句提供表中每个列的值。如果您不知道表格中列的顺序,请使用
查找。
DESCRIBE
tbl_name
一个SET子句通过名称明确指示列,以及指定每个列的值。
列值可以用几种方式给出:
如果未启用严格SQL模式,则未明确给定值的任何列都将设置为其默认(显式或隐式)值。例如,如果您指定的列列表未指定表中的所有列,则未命名的列将设置为其默认值。默认值分配在 第11.7节“数据类型默认值”中介绍。另见 第1.8.3.3节“对无效数据的约束”。
如果启用严格SQL模式,则如果
INSERT语句没有为没有默认值的每列指定显式值,则语句会生成错误。请参见
第5.1.8节“服务器SQL模式”。
如果列列表和VALUES列表均为空,则INSERT创建一行,每列设置为其默认值:
INSERT INTO tbl_name()VALUES();
如果未启用严格模式,则MySQL将对任何未明确定义默认值的列使用隐式默认值。如果启用了严格模式,如果任何列没有默认值,则会发生错误。
使用关键字DEFAULT将列明确设置为其默认值。这样可以更轻松地编写
INSERT将值分配给除了几列以外的所有列的语句,因为它使您可以避免编写VALUES不包含表中每列的值的不完整列表。否则,您必须提供与列表中每个值相对应的列名称VALUES
列表。
如果生成的列被明确插入,则唯一允许的值是DEFAULT。有关生成列的信息,请参见
第13.1.18.8节“CREATE TABLE和Generated Columns”。
在表达式中,您可以使用它
来生成列的默认值
。
DEFAULT(col_name)col_name
expr如果表达式数据类型与列数据类型不匹配,则可能会发生提供列值
的表达式的类型转换
。根据列的类型,给定值的转换可能会导致不同的插入值。例如,将所述字符串'1999.0e-2'
成INT,
FLOAT,
DECIMAL(10,6),或
YEAR列中的值插入
1999,19.9921,
19.992100,或1999,分别。存储在INT和
YEAR列中的值
是
1999因为字符串到数字的转换只能看作字符串的初始部分,因为它可能被认为是一个有效的整数或年份。对于
FLOAT和
DECIMAL列,字符串到数字的转换将整个字符串视为有效的数字值。
表达式expr可以引用先前在值列表中设置的任何列。例如,您可以这样做,因为之前分配的col2
引用的值为col1:
INSERT INTO tbl_name(col1,col2)VALUES(15,col1 * 2);
但是,以下是不合法的,因为价值
col1是指col2,这是后分配col1:
INSERT INTO tbl_name(col1,col2)VALUES(col2 * 2,15);
包含AUTO_INCREMENT值的列发生异常
。由于
AUTO_INCREMENT值是在其他值赋值后生成的AUTO_INCREMENT,因此对赋值中列的任何引用都会
返回a 0。
INSERT使用
VALUES语法的语句可以插入多行。为此,请包含逗号分隔列值的多个列表,列表中括号内用逗号分隔。例:
INSERT INTO tbl_name(a,b,c)VALUES(1,2,3),(4,5,6),(7,8,9);
每个值列表必须包含与每行要插入的值完全相同的值。以下语句无效,因为它包含九个值的一个列表,而不是每个三个值的三个列表:
INSERT INTO tbl_name(a,b,c)VALUES(1,2,3,4,5,6,7,8,9);
VALUE是VALUES在这种情况下的同义词
。既不包含任何关于值列表的数量,也不包含关于每个列表的值的数量。无论是单个值列表还是多个列表都可以使用,也可以使用每个列表的值数量。
INSERT可以使用ROW_COUNT()SQL函数或
mysql_affected_rows()C API函数获取
受影响的行值
。请参见第12.14节“信息函数”和
第27.8.7.1节“mysql_affected_rows()”。
如果您使用INSERT ...
VALUES具有多个值列表的语句,或者
INSERT ...
SELECT该语句以此格式返回一个信息字符串:
记录:N1重复:N2警告:N3
如果您使用C API,则可以通过调用该mysql_info()
函数来获取信息字符串。请参见第27.8.7.36节“mysql_info()”。
Records表示语句处理的行数。(这不一定是实际插入的行数,因为它Duplicates可以是非零。)Duplicates表示由于重复某些现有的唯一索引值而无法插入的行数。Warnings表示尝试插入有问题的列值的次数。在下列任何情况下都可能发生警告:
插入NULL已声明的列NOT NULL。对于多行
INSERT语句或
INSERT INTO ...
SELECT语句,该列设置为列数据类型的隐式默认值。这是
0数字类型,字符串类型为空字符串('')
,日期和时间类型为“ 零 ”值。
INSERT INTO ...
SELECT语句的处理方式与多行插入相同,因为服务器不检查结果集SELECT是否返回单行。(对于单行
INSERT,NULL插入a 时不会发生警告
NOT
NULL柱。相反,该语句失败并出现错误。)
将数字列设置为位于列范围之外的值。该值被剪切到范围的最近端点。
将值分配'10.34 a'给数字列。尾随的非数字文本被剥离,剩余的数字部分被插入。如果字符串值没有前导数字部分,则该列设置为
0。
插入一个字符串转换成一个字符串柱(CHAR,
VARCHAR,
TEXT,或
BLOB),其超过了列的最大长度。该值被截断为列的最大长度。
将值插入到数据类型非法的日期或时间列中。列被设置为该类型的适当零值。
如果INSERT将行插入到具有AUTO_INCREMENT列的表中,则可以使用LAST_INSERT_ID()SQL函数或mysql_insert_id()C API函数找到用于该列的值
。
这两个功能并不总是表现一致。有关列的INSERT语句行为AUTO_INCREMENT将在第12.14节“信息函数”和第27.8.7.38节“mysql_insert_id()”中进一步讨论。
该INSERT语句支持以下修饰符:
如果使用LOW_PRIORITY修饰符,则执行该INSERT延迟,直到没有其他客户端正在从表中读取。这包括在现有客户正在阅读时开始阅读的其他客户,并且该INSERT
LOW_PRIORITY声明正在等待。因此,对于INSERT
LOW_PRIORITY发表声明等待很长时间的客户是可能的。
LOW_PRIORITY影响使用仅表级锁定仅存储引擎(如
MyISAM,MEMORY,和
MERGE)。
LOW_PRIORITY通常不应该与MyISAM表一起使用,因为这样做会禁用并发插入。请参见
第8.11.3节“并发插入”。
如果指定HIGH_PRIORITY,则会覆盖该--low-priority-updates选项的效果(
如果服务器是使用该选项启动的)。这也会导致并发插入不被使用。请参见
第8.11.3节“并发插入”。
HIGH_PRIORITY影响使用仅表级锁定仅存储引擎(如
MyISAM,MEMORY,和
MERGE)。
如果使用IGNORE修饰符,则执行该INSERT语句时发生的错误将
被忽略。例如,如果没有IGNORE,重复表中现有UNIQUE索引或
PRIMARY KEY值的行会导致重复键错误,并且语句会中止。与
IGNORE,该行被丢弃,并没有发生错误。忽略的错误会生成警告。
IGNORE对插入到没有找到与给定值匹配的分区的分区表中具有类似的效果。没有IGNORE,这样的
INSERT语句会中止并出错。何时
INSERT
IGNORE使用时,对于包含不匹配值的行,插入操作会自动失败,但会插入匹配的行。有关示例,请参见
第22.2.2节“列表分区”。
如果IGNORE未指定,将触发错误的数据转换会中止语句。使用时
IGNORE,将无效值调整为最接近的值并插入; 产生警告,但声明不中止。您可以使用mysql_info()C API函数确定
实际插入表中的行数。
有关更多信息,请参阅 IGNORE关键字和严格SQL模式的比较。
如果指定ON DUPLICATE KEY UPDATE,行插入,将在导致重复值
UNIQUE索引或者PRIMARY
KEY,一个UPDATE旧行的发生。如果行作为新行插入,则每行受影响的行值为1,如果现有行已更新,则每行受影响的行值为2,如果现有行被设置为其当前值,则每行的受影响行值为0。如果在连接到mysqld时指定了C API函数的CLIENT_FOUND_ROWS标志,则
如果现有行设置为其当前值,受影响的行值为1(而不是0)。请参见第13.2.5.2节“INSERT ... ON DUPLICATE KEY UPDATE语法”。
mysql_real_connect()
INSERT DELAYED在MySQL 5.6中已弃用,并计划最终删除。在MySQL 5.7中,DELAYED修饰符被接受但被忽略。使用INSERT(无
DELAYED)代替。请参见
第13.2.5.3节“INSERT DELAYED语法”。
INSERT使用诸如MyISAM使用表级锁的存储引擎影响分区表
的语句
只锁定实际插入行的那些分区。(对于InnoDB
使用行级锁定的存储引擎,不会发生分区锁定。)有关更多信息,请参见
第22.6.4节“分区和锁定”。
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION(partition_name[,partition_name] ...)]
[(col_name[,col_name] ...)]
选择 ...
[在重复密钥更新assignment_list]
value:
{ expr| 默认}
assignment:
col_name=value
assignment_list:
assignment[,assignment] ...
使用INSERT ...
SELECT,您可以根据SELECT
语句的结果快速地将多行插入表中,该语句可以从一个或多个表中进行选择。例如:
INSERT INTO tbl_temp2(fld_id) SELECT tbl_temp1.fld_order_id FROM tbl_temp1 WHERE tbl_temp1.fld_order_id> 100;
以下条件适用于以下
INSERT ...
SELECT声明:
指定IGNORE忽略会导致重复键违规的行。
该INSERT语句的目标表
可能出现在查询部分的FROM子句中
SELECT。但是,您不能插入到表中并从子查询中的同一个表中进行选择。
在从同一个表中选择并插入时,MySQL创建一个内部临时表来存放来自该表的行SELECT,然后将这些行插入到目标表中。但是,不能使用
INSERT INTO t ... SELECT ... FROM t何时
t是TEMPORARY
表,因为TEMPORARY表不能在同一语句中引用两次。请参见
第8.4.4节“MySQL中使用内部临时表”和
第B.5.6.2节“临时表问题”。
AUTO_INCREMENT 列照常工作。
为确保二进制日志可用于重新创建原始表,MySQL不允许并发插入INSERT
... SELECT语句(请参见
第8.11.3节“并发插入”)。
为了避免模棱两可的列引用的问题当
SELECT与
INSERT指代相同的表中,提供一种用于在所使用的每个表唯一的别名
SELECT在该部分与适当的别名部分,和限定列名。
您可以显式选择源表或目标表(或两者)的哪些分区或子分区(或两者)将与表PARTITION名称后面的选项一起使用。当PARTITION与SELECT语句部分中的源表名称一起使用时,
仅从其分区列表中指定的分区或子分区中选择行。当PARTITION
与INSERT语句部分的目标表名称一起使用时
,必须可以将选定的所有行插入到选项后面的分区列表中命名的分区或子分区中。否则,该INSERT ...
SELECT陈述失败。有关更多信息和示例,请参阅第22.5节“分区选择”。
有关INSERT
... SELECT语句,请参见
第13.2.5.2节“INSERT ... ON DUPLICATE KEY UPDATE语法”,以了解SELECT可在某个ON DUPLICATE KEY UPDATE
子句中引用列的条件。
SELECT
没有ORDER BY子句的语句返回行
的顺序是不确定的。这意味着,在使用复制时,不能保证这样的
SELECT返回在主服务器和从服务器上的顺序相同,这可能会导致它们之间的不一致。为防止发生这种情况,应始终INSERT ... SELECT使用ORDER BY
在主服务器和从服务器上产生相同行顺序的子句编写要复制的语句。另请参见第16.4.1.17节“复制和限制”。
由于这个问题,
INSERT ...
SELECT ON DUPLICATE KEY UPDATE并且
INSERT IGNORE ...
SELECT语句被标记为不安全的基于语句的复制。这些语句在使用基于语句的模式时会在错误日志中产生警告,并在使用MIXED模式时使用基于行的格式写入二进制日志
。(错误#11758262,错误#50439)
另请参见第16.2.1.1节“基于声明和基于行的复制的优点和缺点”。
INSERT ... SELECT影响使用诸如MyISAM使用表级锁的存储引擎的分区表
的语句
会锁定目标表的所有分区; 但是,只有实际从源表读取的分区才会被锁定。(对于使用存储引擎的表(例如InnoDB使用行级锁定的表),不会发生这种情况。)有关更多信息,请参见
第22.6.4节“分区和锁定”。
如果指定ON DUPLICATE KEY UPDATE
要插入会在导致重复值条款和行UNIQUE索引或者PRIMARY
KEY,一个UPDATE旧行的发生。例如,如果列a被声明为UNIQUE并且包含该值
1,则以下两个语句具有相似的效果:
INSERT INTO t1(a,b,c)VALUES(1,2,3) 在DUPLICATE KEY UPDATE上c = c + 1; UPDATE t1 SET c = c + 1 WHERE a = 1;
(对于自动增量列的InnoDB
表格,其效果并不相同,a使用自动增量列时,INSERT
语句会增加自动增量值,但
UPDATE不会。)
如果列b也是唯一的,
INSERT则等价于此
UPDATE语句:
UPDATE t1 SET c = c + 1 WHERE a = 1 OR b = 2 LIMIT 1;
如果a=1 OR b=2几个行相匹配,只有
一个行被更新。通常,您应该尽量避免ON DUPLICATE KEY UPDATE
在具有多个唯一索引的表上使用子句。
使用时ON DUPLICATE KEY UPDATE,如果行作为新行插入,则每行受影响的行值为1,如果更新现有行,则每行受影响的行值为2;如果现有行被设置为其当前值,则每行受影响的行值为0。如果在连接到mysqld时指定了C API函数的
CLIENT_FOUND_ROWS标志,
如果现有行设置为其当前值,受影响的行值为1(而不是0)。
mysql_real_connect()
如果一个表包含一AUTO_INCREMENT列并INSERT
... ON DUPLICATE KEY UPDATE插入或更新一行,该LAST_INSERT_ID()函数将返回该AUTO_INCREMENT值。
该ON DUPLICATE KEY UPDATE子句可以包含多个列分配,用逗号分隔。
在ON DUPLICATE KEY
UPDATE子句中的赋值表达式中,可以使用该
函数来引用语句部分中的
列值
。换句话说,
在子句中指的是将插入的值,没有发生重复键冲突。这个函数在多行插入中特别有用。该
函数仅在子句或
语句中有意义,否则返回
。例:
VALUES(col_name)INSERTINSERT ...
ON DUPLICATE KEY UPDATEVALUES(col_name)ON DUPLICATE KEY UPDATEcol_nameVALUES()ON DUPLICATE KEY UPDATEINSERTNULL
INSERT INTO t1(a,b,c)VALUES(1,2,3),(4,5,6) 重复键更新c =值(a)+值(b);
该声明与以下两种声明相同:
INSERT INTO t1(a,b,c)VALUES(1,2,3) 在DUPLICATE KEY UPDATE上c = 3; INSERT INTO t1(a,b,c)VALUES(4,5,6) 在DUPLICATE KEY UPDATE上c = 9;
对于INSERT
... SELECT语句,这些规则适用于SELECT您可以在ON DUPLICATE KEY
UPDATE条款中引用的可接受形式的查询表达式:
引用来自单个表(可能是派生表)的查询中的列。
引用多个表上联接的查询中的列。
引用DISTINCT
查询中的列。
引用其他表中的列,只要
SELECT不使用
GROUP BY。一个副作用是您必须限定对非唯一列名称的引用。
来自a的列的引用
UNION不能可靠地工作。要解决此限制,请将UNION其重写
为派生表,以便将其行视为单表结果集。例如,此语句可能会产生不正确的结果:
INSERT INTO t1(a,b) SELECT c,d FROM t2 联盟 SELECT e,f FROM t3 在DUPLICATE KEY UPDATE上b = b + c;
相反,使用重写UNION派生表的等效语句
:
INSERT INTO t1(a,b) 选择*从 (SELECT c,d FROM t2 联盟 SELECT e,f FROM t3)AS dt 在DUPLICATE KEY UPDATE上b = b + c;
将查询重写为派生表的技术还支持引用GROUP BY
查询中的列。
由于INSERT ...
SELECT语句的结果
取决于来自SELECT和这个顺序的行的顺序,并不总能得到保证,所以记录INSERT ...
SELECT ON DUPLICATE KEY UPDATE主站和从站的语句可能会发生
分歧。因此,INSERT ...
SELECT ON DUPLICATE KEY UPDATE对于基于语句的复制,
语句被标记为不安全。这些语句在使用基于语句的模式时会在错误日志中产生警告,并在使用MIXED模式时使用基于行的格式写入二进制日志。INSERT ...
ON DUPLICATE KEY UPDATE针对具有多个唯一或主键的表的
声明也被标记为不安全。(Bug#11765650,错误#58637)
另请参见第16.2.1.1节“基于声明和基于行的复制的优点和缺点”。
一个INSERT ... ON DUPLICATE KEY UPDATE使用的存储引擎,诸如分区表
MyISAM,其使用表级锁锁定在其中一个分区键列被更新表中的任何分区。(对于使用存储引擎的表(如InnoDB使用行级锁定的表),不会发生这种情况。)有关更多信息,请参见
第22.6.4节“分区和锁定”。
INSERT DELAYED ...
该语句的DELAYED选项
INSERT是对标准SQL的MySQL扩展。在以前的MySQL版本中,它可以用于某些类型的表(比如
MyISAM),这样当客户端使用时
INSERT DELAYED,它可以立即从服务器得到一个好的结果,并且在表不是由任何其他线程使用。
DELAYED插入和替换在MySQL 5.6中被弃用。在MySQL 5.7中,
DELAYED不支持。服务器识别但忽略DELAYED关键字,将插入处理为非延迟插入,并生成
ER_WARN_LEGACY_SYNTAX_CONVERTED警告(“ 不再支持INSERT DELAYED。语句已转换为INSERT ”)。该DELAYED
关键字计划在未来版本中删除。
载入数据[LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE'file_name' [REPLACE | 忽视] INTO TABLEtbl_name[PARTITION(partition_name[,partition_name] ...)] [字符集charset_name] [{FIELDS | 列} [TERMINATED BY'string'] [[OPTIONALLY] ENCLOSED BY'char'] [ESCAPED BY'char'] ] [LINES [开头为'string'] [TERMINATED BY'string'] ] [IGNOREnumber{LINES | ROWS}] [(col_name_or_user_var[,col_name_or_user_var] ...)] [SETcol_name= {expr| 默认}, [,col_name= {expr| DEFAULT}] ...]
该LOAD DATA
INFILE语句以非常高的速度从文本文件读取表格到表格中。
LOAD DATA
INFILE是的补充
SELECT ... INTO
OUTFILE。(请参见第13.2.9.1节“SELECT ... INTO语法”。)要将表中的数据写入文件,请使用
SELECT ... INTO
OUTFILE。要将文件读回到表中,请使用
LOAD DATA
INFILE。两种语句的语法FIELDS和
LINES语句都是相同的。两个子句都是可选的,但FIELDS必须先LINES指定两者。
您还可以使用mysqlimport实用程序加载数据文件
; 它通过向LOAD DATA
INFILE服务器发送语句来运行
。该
--local选项会导致
mysqlimport从客户端主机读取数据文件。--compress如果客户端和服务器支持压缩协议,则可以指定该
选项以在慢速网络上获得更好的性能。请参见
第4.5.5节“ mysqlimport - 数据导入程序”。
有关INSERT对比
LOAD DATA
INFILE和加速
的效率的更多信息
LOAD DATA
INFILE,请参见第8.2.4.1节“优化INSERT语句”。
文件名必须以文字字符串形式给出。在Windows上,在路径名称中将反斜杠指定为正斜杠或反斜杠。该
character_set_filesystem系统变量控制文件名的解释。
LOAD DATA支持使用PARTITION带有一个或多个以分号,子分区或两者的逗号分隔名称列表的选项显式分区选择。使用此选项时,如果文件中的任何行无法插入到列表中指定的任何分区或子分区中,则语句会失败,并显示错误发现行不匹配给定的分区集。有关更多信息和示例,请参见
第22.5节“分区选择”。
对于使用使用表锁的存储引擎的分区表,例如MyISAM,LOAD
DATA不能修剪任何分区锁。这不适用于使用使用行级锁定的存储引擎的表,例如InnoDB。有关更多信息,请参见
第22.6.4节“分区和锁定”。
服务器使用由character_set_database系统变量指示的字符集
来解释文件中的信息。
SET NAMES并且设置
character_set_client不影响输入的解释。如果输入文件的内容使用与默认值不同的字符集,通常最好使用该CHARACTER SET子句指定文件的字符集
。binary指定“ 不转换 ”的字符集
。”
LOAD DATA
INFILE将文件中的所有字段解释为具有相同的字符集,而不考虑装入字段值的列的数据类型。为了正确解释文件内容,您必须确保它是用正确的字符集编写的。例如,如果您使用mysqldump -T编写数据文件
或通过SELECT ... INTO
OUTFILE在mysql中发布
语句,请务必使用一个--default-character-set选项,以便在文件加载时使用的字符集中写入输出LOAD DATA
INFILE。
这是不可能的加载使用数据文件
ucs2,utf16,
utf16le,或者utf32
字符集。
如果使用LOW_PRIORITY,LOAD DATA则会延迟执行
语句,直到没有其他客户端正在从表中读取数据。这会影响只使用表级锁只存储引擎(例如
MyISAM,MEMORY和
MERGE)。
如果使用满足并发插入条件CONCURRENT的MyISAM表(即中间不包含空闲块)指定满足条件的
表,则其他线程可以在LOAD DATA执行时从表中检索数据
。LOAD
DATA即使没有其他线程同时使用该表,该选项也会影响某个位的性能。
使用基于行的复制,CONCURRENT无论MySQL版本如何,都会被复制。使用基于语句的复制CONCURRENT不会在MySQL 5.5.1之前复制(请参阅错误#34628)。有关更多信息,请参见
第16.4.1.18节“复制和加载数据INFILE”。
该LOCAL关键字影响的文件和错误处理预期的位置,如下文所述。
LOCAL只有当你的服务器和你的客户端都被配置为允许它时才起作用。例如,如果
mysqld是在local_infile禁用系统变量的情况下启动的
,LOCAL则不起作用。请参见
第6.1.6节“LOAD DATA LOCAL的安全问题”。
该LOCAL关键字将影响该文件预计将发现:
如果LOCAL指定,则该文件由客户端主机上的客户端程序读取并发送到服务器。该文件可以作为完整路径名来指定其确切位置。如果作为相对路径名给出,则名称将相对于客户机程序启动的目录进行解释。
使用LOCAL时
LOAD DATA,将在服务器的临时目录中创建该文件的副本。这
不是由tmpdiror
的值确定的目录slave_load_tmpdir,而是操作系统的临时目录,并且不能在MySQL服务器中配置。(通常,系统临时目录/tmp位于Linux系统和C:\WINDOWS\TEMPWindows上。)在此目录中缺少足够的副本空间可能会导致LOAD DATA
LOCAL语句失败。
如果LOCAL未指定,则该文件必须位于服务器主机上,并由服务器直接读取。服务器使用以下规则来查找该文件:
如果文件名是绝对路径名,则服务器按照给定的名称使用它。
如果文件名是包含一个或多个主要组件的相对路径名,则服务器将搜索与服务器的数据目录相关的文件。
如果给出了没有前导组件的文件名,服务器将在默认数据库的数据库目录中查找该文件。
在这种LOCAL情况下,这些规则意味着./myfile.txt从服务器的数据目录myfile.txt读取名为as的文件,而从默认数据库的数据库目录读取名为as的文件
。例如,如果
db1是默认数据库,则即使该语句显式地将文件加载到数据库中的表中,以下
LOAD DATA语句也会data.txt从数据库目录中
读取该文件
:
db1db2
LOAD DATA INFILE'data.txt'INTO TABLE db2.my_table;
非LOCAL加载操作读取位于服务器上的文本文件。出于安全原因,这些操作要求您有FILE
权限。请参见第6.2.1节“MySQL提供的权限”。另外,非LOCAL加载操作受制于
secure_file_priv系统变量设置。如果变量值是非空目录名称,则要加载的文件必须位于该目录中。如果变量值为空(这是不安全的),则该文件只能由服务器读取。
使用LOCAL比让服务器直接访问文件慢一点,因为文件的内容必须通过客户端连接发送到服务器。另一方面,您不需要FILE加载本地文件的
权限。
LOCAL 也影响错误处理:
随着LOAD DATA
INFILE,数据解释和重复键错误终止操作。
随着LOAD DATA
LOCAL INFILE数据解释和重复键错误变成警告,并且操作继续,因为服务器在操作过程中无法停止文件的传输。对于重复键错误,这与IGNORE指定时相同。
IGNORE将在本节后面进一步解释。
使用REPLACE和IGNORE
关键字控制处理在唯一键值上复制现有行的输入行:
如果指定REPLACE,则输入行会替换现有行。换句话说,对于主键或唯一索引具有与现有行相同的值的行。请参见
第13.2.8节“REPLACE语法”。
如果指定IGNORE,则丢弃在唯一键值上复制现有行的行。有关更多信息,请参阅IGNORE关键字和严格SQL模式的比较。
如果您不指定任一选项,则行为取决于是否LOCAL指定了关键字。如果没有LOCAL,找到重复的键值时会发生错误,并忽略文本文件的其余部分。与LOCAL,默认行为是相同的,如果IGNORE指定; 这是因为服务器无法在操作过程中停止传输文件。
要在加载操作期间忽略外键约束,请SET foreign_key_checks = 0在执行前发出语句LOAD DATA。
如果您LOAD DATA
INFILE在空MyISAM表上使用,则所有非唯一索引将在单独的批处理中创建(如下
REPAIR TABLE)。通常,LOAD DATA
INFILE当你有很多索引时,这会
更快。在某些极端情况下,您可以通过ALTER TABLE ... DISABLE KEYS
在将文件加载到表中之前关闭它们,并使用ALTER
TABLE ... ENABLE KEYS在加载文件之后重新创建索引来更快地创建索引。请参见第8.2.4.1节“优化INSERT语句”。
对于LOAD DATA
INFILE和
SELECT ... INTO
OUTFILE语句,FIELDS和LINES子句的语法
是相同的。两个子句都是可选的,但FIELDS
必须先LINES指定两者。
如果你指定一个FIELDS子句,它的每个子句(TERMINATED BY,
[OPTIONALLY] ENCLOSED BY和ESCAPED
BY)也是可选的,除了你必须至少指定其中的一个。
如果您指定no FIELDS或
LINESclause,则默认值与您写下此内容相同:
'\ t'封闭的字段''ESCAPED BY'\\' '\ n'开头为''的行终止
(反斜线在SQL语句的字符串中的MySQL的转义字符,所以来指定一个反斜杠,必须指定两个反斜杠该值被解释为一个反斜杠。转义序列'\t'和
'\n'分别指定选项卡和换行符,。)
换句话说,LOAD DATA
INFILE读取输入时默认值会导致
如下操作:
在换行符处查找行边界。
不要跳过任何行前缀。
将选项卡中的行分成几个字段。
不要期望字段被包含在任何引用字符中。
将转义字符前面的字符解释
\为转义序列。例如,
\t,\n,和
\\分别表示选项卡,换行,反斜线。有关FIELDS ESCAPED
BY转义序列的完整列表,请参阅后面的讨论。
相反,SELECT ... INTO
OUTFILE写入输出时默认值会导致
如下操作:
在字段之间填写标签。
不要将字段用任何引号括起来。
使用\逃脱制表符,换行符的情况下,或\字段值内出现。
在行尾写新行。
如果您在Windows系统上生成了文本文件,则可能需要使用LINES TERMINATED BY '\r\n'
该文件才能正确读取该文件,因为Windows程序通常使用两个字符作为行终止符。有些程序,例如
写字板,\r在编写文件时可能会用作行终止符。要阅读这些文件,请使用
LINES TERMINATED BY '\r'。
如果您想要读取的所有行都有一个要忽略的公共前缀,则可以使用跳过前缀以及前面的任何内容。如果一行不包含前缀,则整行将被跳过。假设您发出以下语句:
LINES STARTING BY
'prefix_string'
LOAD DATA INFILE'/tmp/test.txt'INTO TABLE测试 FIELDS TERMINATED BY','LINES STARTING BY'xxx';
如果数据文件如下所示:
XXX “ABC”,1 某事xxx“def”,2 “GHI”,3
结果行将("abc",1)和
("def",2)。文件中的第三行被跳过,因为它不包含前缀。
该选项可用于忽略文件开头处的行。例如,您可以使用跳过包含列名称的初始标题行:
IGNORE number
LINESIGNORE 1
LINES
LOAD DATA INFILE'/tmp/test.txt'INTO TABLE test IGNORE 1 LINES;
当您使用SELECT
... INTO OUTFILE亦随
LOAD DATA
INFILE到数据库中的数据写入一个文件,然后读取文件到数据库后,两个语句的field-和line-handling选项必须匹配。否则,
LOAD DATA
INFILE不会正确解释文件的内容。假设您使用
SELECT ... INTO
OUTFILE写入由逗号分隔的字段的文件:
SELECT * INTO OUTFILE'data.txt' 领域终止',' FROM table2;
重新读取逗号分隔的文件,正确的语句是:
LOAD DATA INFILE'data.txt'INTO TABLE table2 FIELDS TERMINATED BY',';
如果您尝试使用下面显示的语句读取文件,则它不起作用,因为它指示
LOAD DATA
INFILE在字段之间查找选项卡:
LOAD DATA INFILE'data.txt'INTO TABLE table2 '\ t'的字段终止;
可能的结果是每条输入行将被解释为单个字段。
LOAD DATA
INFILE可以用来读取从外部获取的文件。例如,许多程序都可以以逗号分隔值(CSV)格式导出数据,以便行中的字段用逗号分隔,并用双引号括起来,并带有最初的一行列名。如果此文件中的行由回车/换行符对终止,则此处显示的语句显示了用于加载文件的字段和行处理选项:
LOAD DATA INFILE'data.txt'INTO TABLE tbl_name
“终止的领域”,“封闭的”,“
LINES终止于'\ r \ n'
IGNORE 1 LINES;
如果输入值不一定包含在引号内,请OPTIONALLY在ENCLOSED BY关键字之前
使用。
任何字段或行处理选项都可以指定一个空字符串('')。如果不是空的,FIELDS
[OPTIONALLY] ENCLOSED BY和FIELDS ESCAPED
BY值必须是一个单个字符。该
FIELDS TERMINATED BY,LINES STARTING
BY和LINES TERMINATED BY值可以不止一个字符。例如,要编写以回车/换行符对结尾的行或者读取包含这些行的文件,请指定一个LINES TERMINATED BY
'\r\n'子句。
要读取包含由包含的行分隔的笑话的文件%%,您可以执行此操作
CREATE TABLE笑话 (一个INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 笑话TEXT NOT NULL); LOAD DATA INFILE'/tmp/jokes.txt'INTO TABLE笑话 ''字段终止 LINES终止于'\ n %% \ n'(笑话);
FIELDS [OPTIONALLY] ENCLOSED BY控制字段的引用。对于output(SELECT ... INTO
OUTFILE),如果您省略了单词
OPTIONALLY,则所有字段均由ENCLOSED BY字符括起来
。这种输出的例子(使用逗号作为字段分隔符)如下所示:
“1”,“一串”,“100.20” “2”,“包含逗号的字符串”,“102.20” “3”,“包含”quote“的字符串,”102.20“ “4”,“包含”,“引号和逗号”的字符串,“102.20”
如果指定OPTIONALLY的
ENCLOSED BY字符仅用于从具有字符串数据类型(如柱围值
CHAR,
BINARY,
TEXT,或
ENUM):
1,“一串”,100.20 2,“一个包含逗号的字符串”,102.20 3“,一个包含”quote“的字符串,102.20 4“,一个包含”,引号和逗号“的字符串,102.20
ENCLOSED BY字符值内字符的
出现通过在字符前添加字符来转义
ESCAPED BY。此外,如果您指定一个空ESCAPED BY值,则可能会无意中生成无法正确读取的输出
LOAD DATA
INFILE。例如,如果转义字符为空,则刚才显示的上述输出将显示如下。请注意,第四行中的第二个字段在报价后面包含一个逗号(错误地)似乎是终止该字段:
1,“一串”,100.20 2,“一个包含逗号的字符串”,102.20 3“,一个包含”quote“的字符串,102.20 4“,一个包含”,引号和逗号“的字符串,102.20
对于输入,ENCLOSED BY字符(如果存在)从字段值的末尾剥离。(不管是否OPTIONALLY指定,这都是真的;
OPTIONALLY对输入解释没有影响。)ENCLOSED BY
字符前面的ESCAPED BY字符的出现被解释为当前字段值的一部分。
如果字段以ENCLOSED BY
字符开头,那么该字符的实例只有在字段或行TERMINATED BY序列后面才被识别为终止字段值
。为避免歧义,ENCLOSED BY字段值内的字符出现次数可以加倍并被解释为字符的单个实例。例如,如果ENCLOSED BY
'"'指定,引号的处理方式如下所示:
“The”“BIG”“boss” - >“BIG”老板 “BIG”老板 - >“BIG”老板 “”BIG“”boss - >“BIG”“boss
FIELDS ESCAPED BY 控制如何读取或写入特殊字符:
对于输入来说,如果FIELDS ESCAPED BY
字符不是空的,则该字符的出现被剥离,并且下面的字符被逐字地作为字段值的一部分。某些双字符序列是例外,其中第一个字符是转义字符。这些序列显示在下表中(
\用于转义字符)。NULL本节后面将介绍处理规则
。
有关\-escape语法的更多信息,请参见第9.1.1节“字符串文字”。
如果FIELDS ESCAPED BY字符为空,则不会发生转义序列解释。
对于输出,如果FIELDS ESCAPED BY
字符不为空,则用于输出前面的以下字符:
该FIELDS ESCAPED BY字符
该FIELDS [OPTIONALLY] ENCLOSED BY
字符
FIELDS TERMINATED
BY和LINES TERMINATED BY
值
的第一个字符
ASCII 0(转义字符后面实际写入的是ASCII
0,而不是零值字节)
如果该FIELDS ESCAPED BY字符为空,则不会转义字符,NULL
而是输出为NULL,而不是
\N。指定一个空的转义字符可能不是一个好主意,特别是如果数据中的字段值包含刚才给出的列表中的任何字符。
在某些情况下,现场和线路处理选项会相互影响:
如果LINES TERMINATED BY是空字符串且FIELDS TERMINATED BY非空,则行也以终止FIELDS TERMINATED
BY。
如果FIELDS TERMINATED BY和
FIELDS ENCLOSED BY值都为空(''),则使用固定行(无限制)格式。使用固定行格式,字段之间不使用分隔符(但仍可以有行终止符)。而是使用足够宽的字段来读取和写入列值,以保存字段中的所有值。为
TINYINT,
SMALLINT,
MEDIUMINT,
INT,和
BIGINT,场宽度是4,6,8,11,和20,分别,不管声明显示宽度是什么。
LINES TERMINATED BY仍然用于分隔线条。如果一行不包含所有字段,则其余列将设置为其默认值。如果你没有行结束符,你应该设置它
''。在这种情况下,文本文件必须包含每行的所有字段。
固定行格式也影响NULL值的处理
,如后面所述。
如果您使用多字节字符集,则固定大小格式不起作用。
处理NULL值取决于
使用中的选项FIELDS和LINES选项:
对于默认值FIELDS和
LINES值,NULL被写\N为输出的字段值,并且字段值\N被读取
NULL为输入(假定
ESCAPED BY字符是
\)。
如果FIELDS ENCLOSED BY不为空,则将包含字面值NULL作为其值的字段读取为NULL值。这与字符中NULL包含
的单词不同,FIELDS ENCLOSED BY字符被读作字符串'NULL'。
如果FIELDS ESCAPED BY是空的,
NULL则写为单词
NULL。
使用固定行格式(当FIELDS
TERMINATED BY和FIELDS ENCLOSED
BY两者均为空时使用)NULL被写为空字符串。这会导致
NULL表中的值和空字符串在写入文件时无法区分,因为两者都写为空字符串。如果您需要在重新读取文件时能够将两者分开,则不应使用固定行格式。
尝试加载NULL到NOT
NULL列会导致为列的数据类型和警告分配隐式默认值,或者在严格SQL模式下分配错误。第11.7节“数据类型默认值”中讨论了隐式缺省值
。
有些情况不支持
LOAD DATA
INFILE:
固定大小的行(FIELDS TERMINATED BY并且
FIELDS ENCLOSED BY都是空)和
BLOB或
TEXT列。
如果指定一个分隔符与另一个分隔符相同或作为另一个分隔符的前缀,LOAD
DATA INFILE则无法正确解释输入。例如,以下FIELDS子句会导致问题:
''''封闭''''
如果FIELDS ESCAPED BY为空,则包含该值的发生FIELDS ENCLOSED
BY或LINES TERMINATED BY
后面的字段FIELDS TERMINATED BY值会导致LOAD DATA
INFILE太早停止读取字段或行。发生这种情况是因为
LOAD DATA
INFILE无法正确确定字段或行值的结束位置。
以下示例加载表的所有列
persondata:
LOAD DATA INFILE'persondata.txt'INTO TABLE persondata;
默认情况下,如果在LOAD DATA
INFILE语句末尾没有提供列列表
,则预计输入行将包含每个表列的字段。如果您只想加载某些表格的列,请指定列列表:
LOAD DATA INFILE'persondata.txt'INTO TABLE persondata (col_name_or_user_var[,col_name_or_user_var] ...);
如果输入文件中的字段顺序不同于表中列的顺序,则还必须指定列列表。否则,MySQL无法知道如何将输入字段与表列匹配。
每个col_name_or_user_var值都是列名称或用户变量。通过使用用户变量,该
SET子句允许您在将结果分配给列之前对其值进行转换。
SET子句
中的用户变量可以以多种方式使用。以下示例直接使用第一个输入列作为值t1.column1,并将第二个输入列分配给在用于以下值之前进行除法运算的用户变量t1.column2:
LOAD DATA INFILE'file.txt' 进入表t1 (column1,@ var1) SET column2 = @ var1 / 100;
该SET子句可用于提供不是从输入文件派生的值。以下语句设置
column3为当前日期和时间:
LOAD DATA INFILE'file.txt' 进入表t1 (第1栏,第2栏) SET column3 = CURRENT_TIMESTAMP;
您还可以通过将输入值分配给用户变量并且不将该变量分配给表列来放弃输入值:
LOAD DATA INFILE'file.txt' 进入表t1 (column1,@dummy,column2,@dummy,column3);
使用列/变量列表和SET子句受以下限制:
SET子句中的
赋值应该只在赋值运算符的左侧有列名。
您可以在作业的右侧使用子查询
SET。返回要分配给列的值的子查询可能只是标量子查询。此外,您不能使用子查询从正在加载的表中进行选择。
IGNORE子句
忽略的行不针对列/变量列表或
SET子句进行处理。
以固定行格式加载数据时,不能使用用户变量,因为用户变量没有显示宽度。
处理输入行时,LOAD
DATA将其分割为字段,并根据列/变量列表和SET子句使用值(如果存在)。然后将结果行插入表中。如果该表存在BEFORE INSERT或
AFTER INSERT触发器,则分别在插入行之前或之后激活它们。
如果输入行的字段太多,则额外的字段将被忽略,并且警告的数量会增加。
如果输入行的字段太少,则缺少输入字段的表列将被设置为其默认值。默认值分配在 第11.7节“数据类型默认值”中介绍。
空字段值的解释与缺失字段不同:
对于字符串类型,列被设置为空字符串。
对于数字类型,该列设置为0。
对于日期和时间类型,该列设置为该类型的相应 “ 零 ”值。请参见 第11.3节“日期和时间类型”。
如果您在一个INSERTor
UPDATE语句中显式地将一个空字符串显式指定给一个字符串,数字或日期或时间类型,则这些值是相同的值。
如果SQL模式设置为限制值,则处理空白或不正确的字段值与刚描述的不同。例如,如果sql_mode设置为
TRADITIONAL,则空值或'x'数值列(如数值列)的值转换会导致错误,而不会转换为0.(使用
LOCALor IGNORE,即使使用限制sql_mode值,也会发生警告而不是错误
,并且行使用与非限制性SQL模式相同的最接近行为插入,这是因为服务器无法在操作过程中停止传输文件。
TIMESTAMP仅当NULL
列(即,\N)的值存在并且列未声明为允许NULL值时,或者TIMESTAMP列的默认值是当前时间戳,并且该字段被忽略时,才会将列设置为当前日期和时间列出何时指定字段列表。
LOAD DATA
INFILE将所有输入视为字符串,因此您无法像使用语句一样使用数字值ENUM或
SET列
INSERT。所有
ENUM和
SET值必须指定为字符串。
BIT值不能使用二进制符号直接加载(例如,
b'011010')。要解决此问题,请使用该
SET子句去除前导
b'和尾随,'并执行base-2到base-10的转换,以便MySQL将值BIT正确加载到列中:
外壳>cat /tmp/bit_test.txtb'10' b'1111111' shell>mysql testmysql>LOAD DATA INFILE '/tmp/bit_test.txt'INTO TABLE bit_test (@var1)SET b = CAST(CONV(MID(@var1, 3, LENGTH(@var1)-3), 2, 10) AS UNSIGNED);查询OK,2行受影响(0.00秒) 记录:2删除:0跳过:0警告:0 MySQL的>SELECT BIN(b+0) FROM bit_test;+ ---------- + | BIN(b + 0)| + ---------- + | 10 | | 1111111 | + ---------- + 设置2行(0.00秒)
对于二进制表示法BIT中的
0b值(例如
0b011010),请使用此SET
子句来剥离主键0b:
SET b = CAST(CONV(MID(@ var1,3,LENGTH(@ var1)-2),2,10)AS UNSIGNED)
在Unix上,如果您需要LOAD DATA从管道中读取数据,则可以使用以下技术(该示例将该/目录的列表加载到表中db1.t1):
mkfifo /mysql/data/db1/ls.dat chmod 666 /mysql/data/db1/ls.dat find / -ls> /mysql/data/db1/ls.dat& mysql -e“LOAD DATA INFILE'ls.dat'INTO TABLE t1”db1
在这里,您必须运行生成要加载的数据的命令以及在单独的终端上运行mysql命令,或者在后台运行数据生成过程(如上例所示)。如果你不这样做,管道将阻塞,直到mysql 进程读取数据。
当LOAD DATA
INFILE语句结束时,它将以下列格式返回一个信息字符串:
记录:1删除:0跳过:0警告:0
在使用INSERT语句插入值的情况下(参见第13.2.5节“INSERT语法”),会LOAD DATA
INFILE发生警告,除了
在输入行中的字段太少或太多时也会生成警告。
您可以使用SHOW WARNINGS获取第一个max_error_count
警告列表作为有关错误的信息。请参见
第13.7.5.40节“SHOW WARNINGS Syntax”。
如果您使用的是C API,则可以通过调用该mysql_info()函数来获取有关语句的信息
。请参见
第27.8.7.36节“mysql_info()”。
LOAD XML [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE'file_name' [REPLACE | 忽视] INTO TABLE [db_name。]tbl_name[CHARACTER SETcharset_name] [由'<tagname>' 识别的行] [IGNOREnumber{LINES | ROWS}] [(field_name_or_user_var[,field_name_or_user_var] ...)] [SETcol_name= {expr| 默认}, [,col_name= {expr| DEFAULT}] ...]
该LOAD XML语句将数据从XML文件读取到表中。在
file_name必须作为一个字符串。所述tagname可选的在
ROWS IDENTIFIED BY条款也必须给予作为文字串,并且必须由尖括号(包围<和>)。
LOAD XML充当在XML输出模式下运行mysql客户端的补充(即使用该--xml选项启动客户端
)。要将表中的数据写入XML文件,您可以
使用系统shell中的选项和
选项调用mysql客户端,如下所示:
--xml-e
外壳> mysql --xml -e 'SELECT * FROM mydb.mytable' > file.xml
要将文件读回到表中,请使用
LOAD XML
INFILE。默认情况下,该<row>
元素被认为是数据库表行的等价物; 这可以使用该ROWS IDENTIFIED
BY条款进行更改。
该语句支持三种不同的XML格式:
列名称作为属性和列值作为属性值:
< =“ ” =“ ”... />rowcolumn1value1column2value2
列名称作为标签和列值作为这些标签的内容:
<row> <column1>value1</column1> <column2>value2</column2> </row>
列名称是标签的name属性
<field>,值是这些标签的内容:
<行> <field name ='column1'>value1</ field> <field name ='column2'>value2</ field> </行>
这是其他MySQL工具使用的格式,例如 mysqldump。
所有三种格式都可以在同一个XML文件中使用; 导入例程会自动检测每行的格式并正确解释。标签根据标签或属性名称和列名称进行匹配。
下列条款基本上是连续工作以同样的方式
LOAD XML,因为他们对做
LOAD DATA:
LOW_PRIORITY 要么
CONCURRENT
LOCAL
REPLACE 要么 IGNORE
CHARACTER SET
SET
有关这些子句的更多信息, 请参见第13.2.6节“LOAD DATA INFILE语法”。
(是一个或多个逗号分隔的XML字段或用户变量的列表。用于此目的的用户变量的名称必须与来自XML文件的字段的名称匹配,前缀为field_name_or_user_var,
...)@。您可以使用字段名称来仅选择所需的字段。可以使用用户变量来存储相应的字段值以供后续重新使用。
在或子句使第一XML文件中的行被跳过。这与声明的
条款类似。
IGNORE number
LINESIGNORE
number ROWSnumberLOAD
DATAIGNORE ... LINES
假设我们有一个名为person,创建如下所示的表:
USE测试;
CREATE TABLE人(
person_id INT NOT NULL PRIMARY KEY,
fname VARCHAR(40)NULL,
lname VARCHAR(40)NULL,
创建了TIMESTAMP
);
进一步假设该表最初是空的。
现在假设我们有一个简单的XML文件
person.xml,其内容如下所示:
<列表>
<person person_id =“1”fname =“Kapek”lname =“Sainnouine”/>
<person person_id =“2”fname =“Sajon”lname =“Rondela”/>
<person person_id =“3”> <fname> Likame </ fname> <lname>Örrtmons</ lname> </ person>
<person person_id =“4”> <fname> Slar </ fname> <lname> Manlanth </ lname> </ person>
<person> <field name =“person_id”> 5 </ field> <field name =“fname”>气孔</ field>
<field name =“lname”> Milu </ field> </ person>
<person> <field name =“person_id”> 6 </ field> <field name =“fname”> Nirtam </ field>
<field name =“lname”>Sklöd</ field> </ person>
<person person_id =“7”> <fname> Sungam </ fname> <lname>Dulbåd</ lname> </ person>
<person person_id =“8”fname =“Sraref”lname =“Encmelt”/>
</列表>
本示例文件中介绍了前面讨论的每种允许的XML格式。
要将数据导入person.xml到
person表中,可以使用以下语句:
mysql>LOAD XML LOCAL INFILE 'person.xml'- >INTO TABLE person- >ROWS IDENTIFIED BY '<person>';查询OK,8行受影响(0.00秒) 记录:8删除:0跳过:0警告:0
在这里,我们假设它person.xml位于MySQL数据目录中。如果找不到该文件,则会出现以下错误结果:
错误2(HY000):找不到文件'/person.xml'(错误代码:2)
该ROWS IDENTIFIED BY '<person>'子句意味着<person>XML文件中的每个元素都被视为等同于要导入数据的表中的一行。在这种情况下,这是
数据库中的
person表格test。
从服务器的响应中可以看出,有8行被导入到test.person表中。这可以通过一个简单的SELECT
声明来验证:
MySQL的> SELECT * FROM person;
+ ----------- + -------- + ------------ + --------------- ------ +
| person_id | fname | lname | 创建|
+ ----------- + -------- + ------------ + --------------- ------ +
| 1 | Kapek | Sainnouine | 2007-07-13 16:18:47 |
| 2 | Sajon | Rondela | 2007-07-13 16:18:47 |
| 3 | Likame | Örrtmons| 2007-07-13 16:18:47 |
| 4 | Slar | Manlanth | 2007-07-13 16:18:47 |
| 5 | 气孔| 尼鲁| 2007-07-13 16:18:47 |
| 6 | Nirtam | Sklöd| 2007-07-13 16:18:47 |
| 7 | Sungam | Dulbåd| 2007-07-13 16:18:47 |
| 8 | Sreraf | Encmelt | 2007-07-13 16:18:47 |
+ ----------- + -------- + ------------ + --------------- ------ +
集合中的8行(0.00秒)
如本节前面所述,这表明任何或全部3种允许的XML格式可以出现在单个文件中,并可以使用它们读入LOAD XML。
刚刚显示的导入操作的反转 - 即将MySQL表数据转储到XML文件中 - 可以使用系统shell中的mysql客户端完成,如下所示:
shell>mysql --xml -e "SELECT * FROM test.person" > person-dump.xmlshell>cat person-dump.xml<?xml version =“1.0”?> <resultset statement =“SELECT * FROM test.person”xmlns:xsi =“http://www.w3.org/2001/XMLSchema-instance”> <行> <field name =“person_id”> 1 </ field> <field name =“fname”> Kapek </ field> <field name =“lname”> Sainnouine </ field> </行> <行> <field name =“person_id”> 2 </ field> <field name =“fname”> Sajon </ field> <field name =“lname”> Rondela </ field> </行> <行> <field name =“person_id”> 3 </ field> <field name =“fname”> Likema </ field> <field name =“lname”>Örrtmons</ field> </行> <行> <field name =“person_id”> 4 </ field> <field name =“fname”> Slar </ field> <field name =“lname”> Manlanth </ field> </行> <行> <field name =“person_id”> 5 </ field> <field name =“fname”>气孔</ field> <field name =“lname”> Nilu </ field> </行> <行> <field name =“person_id”> 6 </ field> <field name =“fname”> Nirtam </ field> <field name =“lname”>Sklöd</ field> </行> <行> <field name =“person_id”> 7 </ field> <field name =“fname”> Sungam </ field> <field name =“lname”>Dulbåd</ field> </行> <行> <field name =“person_id”> 8 </ field> <field name =“fname”> Sreraf </ field> <field name =“lname”> Encmelt </ field> </行> </结果集>
该--xml选项使
mysql客户端为其输出使用XML格式; 该-e
选项会导致客户端在选项后立即执行SQL语句。请参见第4.5.1节“ mysql - MySQL命令行工具”。
您可以通过创建person表副本并将转储文件导入新表来验证转储是否有效
,如下所示:
mysql>USE test;mysql>CREATE TABLE person2 LIKE person;查询OK,0行受影响(0.00秒) mysql>LOAD XML LOCAL INFILE 'person-dump.xml'- >INTO TABLE person2;查询OK,8行受影响(0.01秒) 记录:8删除:0跳过:0警告:0 MySQL的>SELECT * FROM person2;+ ----------- + -------- + ------------ + --------------- ------ + | person_id | fname | lname | 创建| + ----------- + -------- + ------------ + --------------- ------ + | 1 | Kapek | Sainnouine | 2007-07-13 16:18:47 | | 2 | Sajon | Rondela | 2007-07-13 16:18:47 | | 3 | Likema | Örrtmons| 2007-07-13 16:18:47 | | 4 | Slar | Manlanth | 2007-07-13 16:18:47 | | 5 | 气孔| 尼鲁| 2007-07-13 16:18:47 | | 6 | Nirtam | Sklöd| 2007-07-13 16:18:47 | | 7 | Sungam | Dulbåd| 2007-07-13 16:18:47 | | 8 | Sreraf | Encmelt | 2007-07-13 16:18:47 | + ----------- + -------- + ------------ + --------------- ------ + 集合中的8行(0.00秒)
不要求XML文件中的每个字段都与相应表中的列匹配。没有相应列的字段被跳过。您可以通过首先清空person2表格并删除created列来看到这一点,然后使用LOAD XML我们之前使用的相同
语句,如下所示:
MySQL的>TRUNCATE person2;查询OK,8行受影响(0.26秒) MySQL的>ALTER TABLE person2 DROP COLUMN created;查询OK,0行受影响(0.52秒) 记录:0重复:0警告:0 MySQL的>SHOW CREATE TABLE person2\G*************************** 1. row ******************** ******* 表:person2 创建表:CREATE TABLE`person2`( `person_id` int(11)NOT NULL, `fname` varchar(40)DEFAULT NULL, `lname` varchar(40)DEFAULT NULL, PRIMARY KEY(`person_id`) )ENGINE = InnoDB DEFAULT CHARSET = utf8 一排(0.00秒) mysql>LOAD XML LOCAL INFILE 'person-dump.xml'- >INTO TABLE person2;查询OK,8行受影响(0.01秒) 记录:8删除:0跳过:0警告:0 MySQL的>SELECT * FROM person2;+ ----------- + -------- + ------------ + | person_id | fname | lname | + ----------- + -------- + ------------ + | 1 | Kapek | Sainnouine | | 2 | Sajon | Rondela | | 3 | Likema | Örrtmons| | 4 | Slar | Manlanth | | 5 | 气孔| 尼鲁| | 6 | Nirtam | Sklöd| | 7 | Sungam | Dulbåd| | 8 | Sreraf | Encmelt | + ----------- + -------- + ------------ + 集合中的8行(0.00秒)
在XML文件的每一行中给出字段的顺序不影响操作LOAD XML; 字段顺序可能因行而异,并且不要求与表中对应列的顺序相同。
如前所述,您可以使用
一个或多个XML字段(仅用于选择所需字段)或用户变量(用于存储相应字段值以备后用)的列表。如果要将XML文件中的数据插入到名称与XML字段名称不匹配的表列中,用户变量尤其有用。为了了解它是如何工作的,我们首先创建一个名为
其结构与
表匹配的表,但其列的命名方式不同:
(field_name_or_user_var,
...)individualperson
mysql>CREATE TABLE individual (- >individual_id INT NOT NULL PRIMARY KEY,- >name1 VARCHAR(40) NULL,- >name2 VARCHAR(40) NULL,- >made TIMESTAMP- >); 查询OK,0行受影响(0.42秒)
在这种情况下,您不能直接将XML文件直接加载到表中,因为字段名和列名不匹配:
MySQL的> LOAD XML INFILE '../bin/person-dump.xml' INTO TABLE test.individual;
错误1263(22004):列设置为默认值; NULL在第1行提供给NOT NULL列'individual_id'
发生这种情况是因为MySQL服务器查找匹配目标表的列名称的字段名称。您可以通过将字段值选择到用户变量中来解决此问题,然后使用设置目标表的列等于这些变量的值SET。您可以在单个语句中执行这两个操作,如下所示:
mysql>LOAD XML INFILE '../bin/person-dump.xml'- >INTO TABLE test.individual (@person_id, @fname, @lname, @created)- >SET individual_id=@person_id, name1=@fname, name2=@lname, made=@created;查询OK,8行受影响(0.05秒) 记录:8删除:0跳过:0警告:0 MySQL的>SELECT * FROM individual;+ --------------- + -------- + ------------ + ----------- ---------- + | individual_id | name1 | name2 | 取得| + --------------- + -------- + ------------ + ----------- ---------- + | 1 | Kapek | Sainnouine | 2007-07-13 16:18:47 | | 2 | Sajon | Rondela | 2007-07-13 16:18:47 | | 3 | Likema | Örrtmons| 2007-07-13 16:18:47 | | 4 | Slar | Manlanth | 2007-07-13 16:18:47 | | 5 | 气孔| 尼鲁| 2007-07-13 16:18:47 | | 6 | Nirtam | Sklöd| 2007-07-13 16:18:47 | | 7 | Sungam | Dulbåd| 2007-07-13 16:18:47 | | 8 | Srraf | Encmelt | 2007-07-13 16:18:47 | + --------------- + -------- + ------------ + ----------- ---------- + 集合中的8行(0.00秒)
用户变量的名称必须与XML文件中相应字段的名称相匹配,并添加所需的@前缀以表明它们是变量。用户变量不需要按照与相应字段相同的顺序列出或分配。
使用子句,可以将具有不同定义的数据从同一个XML文件导入到数据库表中。对于这个例子,假设你有一个名为包含以下XML 的文件:
ROWS IDENTIFIED BY
'<tagname>'address.xml
<?xml version =“1.0”?>
<列表>
<person_id =“1”>
<FNAME>罗伯特</ FNAME>
<L-NAME>琼斯</ L-NAME>
<address address_id =“1”street =“Mill Creek Road”zip =“45365”city =“Sidney”/>
<address address_id =“2”street =“Main Street”zip =“28681”city =“Taylorsville”/>
</人>
<person_id =“2”>
<FNAME>玛丽</ FNAME>
<L-NAME>史密斯</ L-NAME>
<address address_id =“3”street =“River Road”zip =“80239”city =“Denver”/>
<! - <address address_id =“4”street =“North Street”zip =“37920”city =“Knoxville”/> - >
</人>
</列表>
test.person在清除表格中的所有现有记录并显示其结构后,
您可以再次使用本节前面定义的表格:
MySQL的<TRUNCATE person;查询OK,0行受影响(0.04秒) MySQL的<SHOW CREATE TABLE person\G*************************** 1. row ******************** ******* 表:人 创建表:CREATE TABLE`person`( `person_id` int(11)NOT NULL, `fname` varchar(40)DEFAULT NULL, `lname` varchar(40)DEFAULT NULL, `created`时间戳NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY(`person_id`) )ENGINE = MyISAM DEFAULT CHARSET = latin1 一排(0.00秒)
现在使用以下语句address在test数据库中
创建一个表
CREATE TABLE:
CREATE TABLE地址(
address_id INT NOT NULL PRIMARY KEY,
person_id INT NULL,
street VARCHAR(40)NULL,
zip INT NULL,
城市VARCHAR(40)NULL,
创建了TIMESTAMP
);
要将XML文件中的数据导入到
person表中,请执行以下
LOAD XML语句,该语句指定行将由<person>元素指定
,如下所示;
mysql>LOAD XML LOCAL INFILE 'address.xml'- >INTO TABLE person- >ROWS IDENTIFIED BY '<person>';查询OK,2行受影响(0.00秒) 记录:2删除:0跳过:0警告:0
您可以使用SELECT声明验证记录是否已导入
:
MySQL的> SELECT * FROM person;
+ ----------- + -------- + ------- + -------------------- - +
| person_id | fname | lname | 创建|
+ ----------- + -------- + ------- + -------------------- - +
| 1 | 罗伯特| 琼斯| 2007-07-24 17:37:06 |
| 2 | Mary | 史密斯| 2007-07-24 17:37:06 |
+ ----------- + -------- + ------- + -------------------- - +
设置2行(0.00秒)
由于<address>XML文件中的元素在表中没有相应的列
person,因此会跳过它们。
要将<address>
元素中的数据导入到address表中,请使用LOAD XML此处显示的
语句:
mysql>LOAD XML LOCAL INFILE 'address.xml'- >INTO TABLE address- >ROWS IDENTIFIED BY '<address>';查询OK,3行受影响(0.00秒) 记录:3删除:0跳过:0警告:0
您可以看到数据是使用SELECT诸如此类的语句导入的
:
MySQL的> SELECT * FROM address;
+ ------------ + ----------- + ----------------- + ------ - + -------------- + --------------------- +
| address_id | person_id | 街道| zip | 城市| 创建|
+ ------------ + ----------- + ----------------- + ------ - + -------------- + --------------------- +
| 1 | 1 | Mill Creek Road | 45365 | 西德尼| 2007-07-24 17:37:37 |
| 2 | 1 | 大街| 28681 | 泰勒斯维尔| 2007-07-24 17:37:37 |
| 3 | 2 | 河道| 80239 | 丹佛| 2007-07-24 17:37:37 |
+ ------------ + ----------- + ----------------- + ------ - + -------------- + --------------------- +
设置3行(0.00秒)
来自<address>XML注释中的元素的数据不会被导入。但是,由于表中有一person_id列,
每个父元素address的person_id属性
值
<person>都
<address> 将
导入到address表中。
安全考虑。
与LOAD DATA声明一样,XML文件从客户端主机到服务器主机的传输是由MySQL服务器启动的。从理论上讲,可以构建一个补丁服务器,告诉客户端程序在LOAD
XML语句中传输服务器选择的文件,而不是客户端命名的文件。这样的服务器可以访问客户端用户读取访问的客户端主机上的任何文件。
在Web环境中,客户端通常从Web服务器连接到MySQL。可以对MySQL服务器运行任何命令的用户可以使用它LOAD XML
LOCAL来读取Web服务器进程读取访问的任何文件。在这种环境下,与MySQL服务器相关的客户端实际上是Web服务器,而不是由连接到Web服务器的用户运行的远程程序。
您可以通过使用--local-infile=0或
启动服务器来禁止从客户端加载XML文件--local-infile=OFF。启动mysql客户端以LOAD XML在客户端会话期间禁用时,也可以使用此选项。
为了防止客户端从服务器加载XML文件,请不要授予FILE相应MySQL用户帐户的权限,或者如果客户端用户帐户已拥有此权限,请取消该权限。
撤销FILE只能从执行权限(或没有在第一时间给予它)让用户LOAD XML
INFILE声明(还有
LOAD_FILE()功能;它并
不能阻止用户执行
LOAD XML LOCAL
INFILE。要禁止这种说法,你必须启动服务器或客户端与--local-infile=OFF。
换句话说,该FILE
特权只影响客户端是否可以读取服务器上的文件; 它与客户端是否可以读取本地文件系统上的文件无关。
对于使用使用表锁的存储引擎的分区表,例如对表中所有分区执行锁定所MyISAM导致的任何锁定LOAD XML。这不适用于使用使用行级锁定的存储引擎的表,例如
InnoDB。有关更多信息,请参见
第22.6.4节“分区和锁定”。
更换[LOW_PRIORITY | 延迟]
[INTO] tbl_name
[PARTITION(partition_name[,partition_name] ...)]
[(col_name[,col_name] ...)]
{VALUES | VALUE}(value_list)[,(value_list)] ...
更换[LOW_PRIORITY | 延迟]
[INTO] tbl_name
[PARTITION(partition_name[,partition_name] ...)]
组 assignment_list
更换[LOW_PRIORITY | 延迟]
[INTO] tbl_name
[PARTITION(partition_name[,partition_name] ...)]
[(col_name[,col_name] ...)]
选择 ...
value:
{ expr| 默认}
value_list:
value[,value] ...
assignment:
col_name=value
assignment_list:
assignment[,assignment] ...
REPLACE工作原理与此类似
INSERT,只是如果表中的旧行与a PRIMARY KEY或UNIQUE
索引的新行具有相同的值,
则在插入新行之前删除旧行。请参见
第13.2.5节“INSERT语法”。
REPLACE是SQL标准的MySQL扩展。它要么插入,要么删除
,插入。对于标准SQL的另一个MySQL扩展 - 插入或
更新 - 请
参见第13.2.5.2节“INSERT ... ON DUPLICATE KEY UPDATE语法”。
DELAYED插入和替换在MySQL 5.6中被弃用。在MySQL 5.7中,DELAYED
不支持。服务器识别但忽略
DELAYED关键字,将替换处理为非延迟替换,并生成
ER_WARN_LEGACY_SYNTAX_CONVERTED警告。(“ REPLACE DELAYED不再被支持,语句被转换为REPLACE。 ”)DELAYED
关键字将在未来的版本中被删除。
所有列的值都取自REPLACE语句中指定的值
。任何缺失的列都会设置为默认值,就像发生的那样
INSERT。您不能引用当前行中的值,并在新行中使用它们。如果您使用诸如此类的分配,则右侧的列名引用被视为
,因此分配等同于。
SET
col_name =
col_name + 1DEFAULT(col_name)SET
col_name =
DEFAULT(col_name) + 1
要使用REPLACE,您必须同时拥有表格INSERT和
DELETE特权。
如果生成的列被显式替换,则唯一允许的值是DEFAULT。有关生成列的信息,请参见
第13.1.18.8节“CREATE TABLE和Generated Columns”。
REPLACE支持使用PARTITION关键字和分区,子分区或两者的逗号分隔名称列表的显式分区选择。同样INSERT,如果无法将新行插入这些分区或子分区中的任何分区,则REPLACE语句会失败,并显示错误发现行不匹配给定的分区集。有关更多信息和示例,请参见
第22.5节“分区选择”。
该REPLACE语句返回一个计数以指示受影响的行数。这是删除和插入的行的总和。如果单行的计数为1,
REPLACE则插入一行并且没有行被删除。如果计数大于1,则在插入新行之前删除一个或多个旧行。如果表包含多个唯一索引,并且新行为不同的唯一索引中的不同旧行重复值,则可以用单个行替换多个旧行。
受影响的行数可以轻松确定是
REPLACE只添加一行还是替换任何行:检查计数是1(增加)还是更大(替换)。
如果您使用的是C API,则可以使用该mysql_affected_rows()函数获取受影响的行数
。
您无法替换为表并从子查询中的同一个表中进行选择。
MySQL为REPLACE(和LOAD DATA ...
REPLACE)使用以下算法
:
尝试将新行插入表中
插入失败,因为主键或唯一索引发生重复键错误:
从表中删除具有重复键值的冲突行
再次尝试将新行插入表中
在重复键错误的情况下,存储引擎可能会执行REPLACE更新而不是删除加插入,但语义相同。除了存储引擎如何增加状态变量的可能差异之外,没有用户可见的效果
。
Handler_xxx
因为REPLACE ... SELECT
语句的结果取决于来自SELECT和这个顺序的行的
顺序并不总能得到保证,所以在记录这些主语句和从属语的语句时可能发生分歧。出于这个原因,
REPLACE ... SELECT语句被标记为不安全的基于语句的复制。这些语句在使用基于语句的模式时会在错误日志中产生警告,并在使用MIXED模式时使用基于行的格式写入二进制日志
。另请参见
第16.2.1.1节“基于声明和基于行的复制的优点和缺点”。
修改未分区以容纳分区的现有表时,或修改已分区表的分区时,可以考虑更改表的主键(请参见
第22.6.1节“分区键,主键和唯一键” “)。您应该意识到,如果您这样做,REPLACE语句的结果
可能会受到影响,就像修改未分区表的主键那样。考虑下面的CREATE TABLE语句创建的表格
:
CREATE TABLE测试( id INT UNSIGNED NOT NULL AUTO_INCREMENT, 数据VARCHAR(64)DEFAULT NULL, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY(id) );
当我们创建这个表并运行mysql客户端中显示的语句时,结果如下所示:
MySQL的>REPLACE INTO test VALUES (1, 'Old', '2014-08-20 18:47:00');查询OK,1行受影响(0.04秒) MySQL的>REPLACE INTO test VALUES (1, 'New', '2014-08-20 18:47:42');查询OK,2行受影响(0.04秒) MySQL的>SELECT * FROM test;+ ---- + ------ + --------------------- + | id | 数据| ts | + ---- + ------ + --------------------- + | 1 | 新增| 2014-08-20 18:47:42 | + ---- + ------ + --------------------- + 一排(0.00秒)
现在我们创建与第一个表几乎相同的第二个表,除了主键现在覆盖2列,如下所示(强调文本):
CREATE TABLE test2(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
数据VARCHAR(64)DEFAULT NULL,
ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(id,ts)
);
当我们在原始表上运行test2相同的两条
REPLACE语句时
test,我们获得了不同的结果:
MySQL的>REPLACE INTO test2 VALUES (1, 'Old', '2014-08-20 18:47:00');查询OK,1行受影响(0.05秒) MySQL的>REPLACE INTO test2 VALUES (1, 'New', '2014-08-20 18:47:42');查询OK,1行受影响(0.06秒) MySQL的>SELECT * FROM test2;+ ---- + ------ + --------------------- + | id | 数据| ts | + ---- + ------ + --------------------- + | 1 | 旧| 2014-08-20 18:47:00 | | 1 | 新增| 2014-08-20 18:47:42 | + ---- + ------ + --------------------- + 设置2行(0.00秒)
这是由于以下事实:在运行时
test2,列值id和
ts列值必须与要替换的行的现有行值相匹配; 否则,插入一行。
甲REPLACE使用存储引擎例如影响分区表声明
MyISAM了采用表级锁锁只有那些含有匹配的行的分区
REPLACE声明WHERE
子句,只要没有表分区的列被更新; 否则整个表被锁定。(对于InnoDB使用行级锁定的存储引擎,不会发生分区锁定。)有关更多信息,请参见
第22.6.4节“分区和锁定”。
选择
[ALL | DISTINCT | DISTINCTROW]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr[,select_expr...]
[从table_references
[PARTITION partition_list]
[WHEREwhere_condition ]
[GROUP BY { col_name| expr| position}
[ASC | DESC],... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY { col_name| expr| position}
[ASC | DESC],...]
[LIMIT {[ offset,] row_count| row_countOFFSET offset}]
[程序procedure_name(argument_list)]
[INTO OUTFILE' file_name'
[字符集charset_name]
export_options
| INTO DUMPFILE' file_name'
| INTO var_name[,var_name]]
[更新| 在共享模式下锁定]]
SELECT用于检索从一个或多个表中选择的行,并且可以包含
UNION语句和子查询。请参见第13.2.9.3节“UNION语法”和第13.2.10 节“子查询语法”。
最常用的
SELECT语句是这些:
每个select_expr表示您想要检索的列。必须至少有一个
select_expr。
table_references指示从中检索行的表格。其语法在第13.2.9.2节“JOIN语法”中描述。
SELECT支持显式分区选择,使用PARTITION列表中的分区或子分区(或两者)列表中的表名table_reference(见
第13.2.9.2节“JOIN语法”)。在这种情况下,仅从列出的分区中选择行,并忽略该表的任何其他分区。有关更多信息和示例,请参见
第22.5节“分区选择”。
SELECT ... PARTITION从使用存储引擎的MyISAM
表(例如执行表级锁(以及因此分区锁))的表中只锁定由该PARTITION选项命名的分区或子分区
。
有关更多信息,请参见 第22.6.4节“分区和锁定”。
该WHERE条款如果给出,则表示行必须满足选择的条件。
where_condition是一个表达式,对于要选择的每一行,其计算结果为true。如果没有WHERE子句,语句将选择所有行
。
在WHERE表达式中,除了汇总(汇总)函数外,您可以使用MySQL支持的任何函数和运算符。请参见
第9.5节“表达式语法”和
第12章函数和操作符。
SELECT 也可以用来检索不参考任何表而计算出的行。
例如:
MySQL的> SELECT 1 + 1;
- > 2
MySQL的> SELECT 1 + 1 FROM DUAL;
- > 2
DUAL纯粹是为了方便那些要求所有SELECT
陈述应该有的人FROM以及其他可能的条款。MySQL可能会忽略这些子句。FROM DUAL如果没有引用表,MySQL不需要
。
通常,使用的子句必须按照语法描述中显示的顺序给出。例如,一个
HAVING条款必须出现在任何GROUP BY条款之后,任何
条款之前ORDER
BY。例外情况是,该
INTO子句可以显示在语法描述中,也可以紧跟在select_expr列表后面
。有关更多信息INTO,请参见第13.2.9.1节“SELECT ... INTO语法”。
select_expr术语
列表包含指示要检索哪些列的选择列表。术语指定一列或表达式或可以使用
*-shorthand:
*可以使用
仅包含一个不合格的选择列表
作为简写来选择所有表中的所有列:
SELECT * FROM t1 INNER JOIN t2 ...
可以用作合格的简写来选择命名表中的所有列:
tbl_name.*
SELECT t1。*,t2。* FROM t1 INNER JOIN t2 ...
*对选择列表中的其他项目
使用不合格可能会产生解析错误。为避免此问题,请使用合格的
参考
tbl_name.*
SELECT AVG(score),t1。* FROM t1 ...
以下列表提供了有关其他SELECT子句的附加信息
:
A select_expr可以使用一个别名。别名用作表达式的列名,并且可以在被使用
,或
条款。例如:
AS
alias_nameGROUP BYORDER BYHAVING
SELECT CONCAT(last_name,',',first_name)AS full_name FROM mytable ORDER BY full_name;
使用标识符对AS别名进行别名时,
该关键字是可选
select_expr的。前面的例子可能是这样写的:
SELECT CONCAT(last_name,',',first_name)full_name FROM mytable ORDER BY full_name;
但是,因为这AS是可选的,所以如果忘记两个select_expr表达式之间的逗号,就会出现一个细微问题
:MySQL将第二个解释为别名。例如,在以下语句中,columnb将被视为别名:
SELECT columna columnb FROM mytable;
出于这个原因,AS在指定列别名时习惯使用明确的习惯。
在WHERE子句中引用列别名是不允许的
,因为在WHERE
执行子句时列值可能还没有确定。参见第B.5.4.4节“列别名问题”。
该子句指示要从中检索行的表或多个表。如果您命名多个表,您正在执行联接。有关join语法的信息,请参见第13.2.9.2节“JOIN语法”。对于指定的每个表,您可以选择指定一个别名。
FROM
table_references
tbl_name[[AS]alias] [index_hint]
索引提示的使用为优化器提供了有关在查询处理期间如何选择索引的信息。有关指定这些提示的语法的说明,请参见 第8.9.4节“索引提示”。
您可以使用
另一种方式强制MySQL选择主键扫描而不是表扫描。请参见
第5.1.5节“服务器系统变量”。
SET
max_seeks_for_key=value
您可以将默认数据库中的表格称为
tbl_name或as
db_name。tbl_name
明确指定数据库。你可以参考一个列
col_name,
tbl_name。col_name,或者
db_name。tbl_name。col_name。你不需要指定一个tbl_nameor
db_name。tbl_name
列引用的前缀,除非引用是不明确的。请参见第9.2.1节“标识符限定符”,了解需要更明确的列参考形式的歧义性示例。
表引用可以使用或
别名
:
tbl_name AS
alias_nametbl_name alias_name
SELECT t1.name,t2.salary FROM employee AS t1,info AS t2 WHERE t1.name = t2.name; SELECT t1.name,t2.salary FROM employee t1,info t2 WHERE t1.name = t2.name;
选择用于输出的列可以
使用列名称,列别名或列位置在in ORDER BY和GROUP BY子句中引用
。列位置是整数并以1开头:
SELECT大学,地区,种子FROM锦标赛 ORDER BY区域,种子; SELECT大学,地区AS r,种子AS s FROM比赛 ORDER BY r,s; SELECT大学,地区,种子FROM锦标赛 ORDER BY 2,3;
要按相反顺序排序,请将DESC
(降序)关键字添加到ORDER BY您排序的子句中的列名称
。默认是升序; 这可以使用ASC关键字明确指定。
如果ORDER BY在子查询中发生,并且在外部查询中应用,则最外层
ORDER BY优先。例如,以下语句的结果按降序排列,而不是升序:
(SELECT ... ORDER BY a)DESC命令;
不赞成使用列位置,因为语法已从SQL标准中删除。
如果您使用GROUP BY,输出行按照列进行排序,就GROUP BY好像您ORDER BY对相同的列进行排序一样。为了避免GROUP BY
产生排序的开销,添加ORDER BY NULL:
SELECT a,COUNT(b)FROM test_table GROUP BY ORDER BY NULL;
依靠隐式GROUP BY排序(即,缺少ASC或
DESC指定者进行排序)已被弃用。要生成给定的排序顺序,请使用显式ASC或
列DESC标识符GROUP
BY或提供一个ORDER BY
子句。
在a中使用ORDER BY或GROUP
BY排序列时
SELECT,服务器仅使用max_sort_length系统变量指示的初始字节数排序值
。
MySQL扩展了该GROUP BY子句,以便您还可以指定子句中命名的列ASC并
DESC在该列之后:
SELECT a,COUNT(b)FROM test_table GROUP BY a DESC;
MySQL扩展了使用GROUP BY以允许选择在GROUP
BY子句中未提及的字段。如果你没有得到你从你的查询所期望的结果,请阅读的描述
GROUP BY中发现的
第12.19,“集合(GROUP BY)功能”。
GROUP BY允许WITH
ROLLUP修饰符。请参见
第12.19.2节“GROUP BY修饰符”。
该HAVING条款几乎适用于将项目发送给客户端之前的几乎没有优化的情况。(LIMIT之后应用
HAVING。)
SQL标准要求HAVING必须仅引用GROUP BY
聚合函数中使用的子句或列中的列。但是,MySQL支持对此行为的扩展,并且允许
HAVING引用
SELECT列表中的列以及外部子查询中的列。
如果该HAVING子句引用不明确的列,则会发生警告。在下面的语句中,col2由于它用作别名和列名称,所以不明确:
SELECT COUNT(col1)as col2 FROM t GROUP BY col2 HAVING col2 = 2;
优先考虑标准的SQL行为,因此如果
在输出列表中HAVING使用列名GROUP BY作为别名列,并且在列中使用列名
作为别名列,则优先选择列中的
GROUP BY列。
不要HAVING用于条款中应该包含的项目WHERE。例如,不要写下面的内容:
SELECTcol_nameFROMtbl_nameHAVINGcol_name> 0;
改为:
SELECTcol_nameFROMtbl_nameWHEREcol_name> 0;
该HAVING子句可以引用聚合函数,WHERE子句不能:
SELECT用户,MAX(工资)FROM用户 GROUP BY用户HAVING MAX(工资)> 10;
(这在一些旧版本的MySQL中不起作用。)
MySQL允许重复列名。也就是说,可以有多个select_expr具有相同的名称。这是对标准SQL的扩展。由于MySQL也允许GROUP BY并
HAVING引用
select_expr值,这可能导致模糊:
SELECT 12 AS a,FROM FROM t GROUP BY a;
在该声明中,两列都有名称
a。要确保使用正确的列进行分组,请为每个名称使用不同的名称
select_expr。
MySQL ORDER BY通过在select_expr值中搜索来解析子句中的
非限定列或别名引用,然后在FROM子句中的表的列中解析
。对于GROUP BY或HAVING
子句,它FROM在搜索select_expr
值之前搜索子句。(对于GROUP BY和
HAVING,这与使用与之相同规则的MySQL 5.0之前的行为不同ORDER
BY。)
该LIMIT子句可用于约束SELECT语句返回的行数
。
LIMIT需要一个或两个数字参数,它们都必须是非负整数常量,但有以下例外:
在准备好的语句中,LIMIT
可以使用?
占位符标记指定参数。
在存储的程序中,LIMIT
可以使用整数值例程参数或局部变量来指定参数。
有两个参数,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。初始行的偏移量为0(不是1):
SELECT * FROM tbl LIMIT 5,10; #检索第6-15行
要从某个偏移量直到结果集的末尾检索所有行,可以使用一些大数目作为第二个参数。该语句检索从第96行到最后一行的所有行:
SELECT * FROM tbl LIMIT 95,18446744073709551615;
使用一个参数,该值指定了从结果集开头返回的行数:
SELECT * FROM tbl LIMIT 5; #检索前5行
换句话说,相当于。
LIMIT
row_countLIMIT 0,
row_count
对于准备好的语句,您可以使用占位符。以下语句将从tbl表中返回一行
:
SET @ a = 1; 从'SELECT * FROM tbl LIMIT'中准备STMT?'; 执行STMT使用@a;
以下语句将返回表中的第二行到第六行tbl:
SET @ skip = 1; SET @ numrows = 5; 从'选择*从tbl LIMIT?,?'中准备STMT。 EXECUTE STMT使用@skip,@numrows;
为了与PostgreSQL兼容,MySQL也支持
语法。
LIMIT row_count OFFSET
offset
如果LIMIT在子查询中发生,并且在外部查询中应用,则最外层
LIMIT优先。例如,以下语句生成两行,而不是一行:
(SELECT ... LIMIT 1)LIMIT 2;
一个PROCEDURE条款的名称应该在结果集中处理数据的过程。有关示例,请参见
第8.4.2.4节“使用PROCEDURE ANALYZE”,其中描述
ANALYSE了可用于获取有助于减小表大小的最佳列数据类型建议的过程。
一个PROCEDURE条款是不是在允许的
UNION声明。
PROCEDURE 从MySQL 5.7.18开始不推荐使用语法,并在MySQL 8.0中删除。
这种SELECT ...
INTO形式SELECT
可以将查询结果写入文件或存储在变量中。有关更多信息,请参见
第13.2.9.1节“SELECT ... INTO语法”。
如果您FOR UPDATE与使用页锁或行锁的存储引擎一起使用,则查询检查的行将被写锁定,直到当前事务结束。使用
LOCK IN SHARE MODE设置共享锁,允许其他事务读取已检查的行,但不更新或删除它们。请参见
第14.5.2.4节“锁定读取”。
另外,你不能在诸如。的声明中
使用FOR UPDATE它的一部分。(如果你尝试这样做,那么在创建' '时,该语句会被拒绝,并且会出现Can not update table' '错误
。)这是MySQL 5.5和更早版本的行为改变,允许
语句在表中进行更改除了正在创建的表格之外。
SELECTCREATE
TABLE new_table SELECT ... FROM
old_table ...old_tablenew_tableCREATE
TABLE ... SELECT
在SELECT关键字之后,可以使用一些影响语句操作的修饰符。HIGH_PRIORITY,
STRAIGHT_JOIN和开头的修饰符
SQL_是对标准SQL的MySQL扩展。
在ALL和DISTINCT
修饰符指定重复行是否应该返回。
ALL(默认值)指定应返回所有匹配的行,包括重复项。
DISTINCT指定从结果集中删除重复的行。指定两个修饰符都是错误的。DISTINCTROW是一个同义词
DISTINCT。
HIGH_PRIORITY给出
SELECT比更新表格的语句更高的优先级。您应该只用于查询速度非常快且必须立即完成的查询。一个
SELECT HIGH_PRIORITY同时表被锁定用于读取发出查询,即使有一个更新语句等待表是自由运行。这会影响只使用表级锁只存储引擎(例如MyISAM,MEMORY和MERGE)。
STRAIGHT_JOIN强制优化器按照它们在FROM条款中列出的顺序加入表
。如果优化器以非最优顺序加入表,可以使用它来加速查询。
STRAIGHT_JOIN也可以在
table_references列表中使用。请参见
第13.2.9.2节“JOIN语法”。
STRAIGHT_JOIN不适用于优化器视为const或
system表的任何
表。这样的表生成单行,在查询执行的优化阶段期间被读取,并且在查询执行继续之前对其列的引用被替换为适当的列值。这些表将首先出现在显示的查询计划中EXPLAIN。请参见
第8.8.1节“使用EXPLAIN优化查询”。此异常可能不适用于const或
system那些在使用的表NULL外的-complemented侧连接(即,a的右侧表LEFT
JOIN或的左侧表RIGHT
JOIN。
SQL_BIG_RESULT或者
SQL_SMALL_RESULT可以用于
GROUP BY或者DISTINCT告诉优化器结果集分别有很多行或很小。因为SQL_BIG_RESULT,MySQL直接使用基于磁盘的临时表(如果它们已创建),并且更喜欢将GROUP BY元素排序为使用临时表和元素上的键。因为
SQL_SMALL_RESULT,MySQL使用内存中的临时表来存储结果表而不是使用排序。这通常不需要。
SQL_BUFFER_RESULT迫使结果被放入临时表中。这有助于MySQL尽早释放表锁,并有助于在需要很长时间将结果集发送到客户端的情况下。此修饰符只能用于顶级SELECT
语句,不能用于子查询或后续
UNION。
SQL_CALC_FOUND_ROWS告诉MySQL计算结果集中有多少行,不考虑任何LIMIT子句。行数然后可以通过检索SELECT
FOUND_ROWS()。参见
第12.14节“信息功能”。
在SQL_CACHE与
SQL_NO_CACHE修饰符影响查询缓存查询结果的缓存(见
第8.10.3,“MySQL查询缓存”)。SQL_CACHE
告诉MySQL将结果存储在查询缓存中,如果缓存可用并且
query_cache_type系统变量的值为2或DEMAND。与SQL_NO_CACHE,服务器不使用查询缓存。它既不检查查询缓存以查看结果是否已被缓存,也不缓存查询结果。
这两个修饰符是互斥的,如果两者都指定了,则会发生错误。而且,这些修饰符在子查询(包括FROM子句中的子查询)以及
SELECT除第一个之外的其他工会中不允许使用这些修饰符
SELECT。
对于视图,SQL_NO_CACHE如果它出现在SELECT查询中的任何位置,则适用。对于可缓存的查询,SQL_CACHE
如果它出现在SELECT查询引用的视图的第一个视图中,则适用
。
查询缓存从MySQL 5.7.20开始已弃用,并在MySQL 8.0中删除。弃用包括
SQL_CACHE和
SQL_NO_CACHE。
甲SELECT从使用存储引擎,诸如分区表MyISAM,其使用表级锁锁仅含有匹配的行这些分区SELECT声明
WHERE子句。(这InnoDB对于使用行级锁定的存储引擎不会发生。)有关更多信息,请参见
第22.6.4节“分区和锁定”。
这种SELECT ...
INTO形式SELECT
可以将查询结果存储在变量中或写入文件中:
SELECT ... INTO
选择列值并将它们存储到变量中。
var_list
SELECT ... INTO OUTFILE将选定的行写入文件。可以指定列和行终止符来产生特定的输出格式。
SELECT ... INTO DUMPFILE 在没有任何格式的情况下将一行写入文件。
在SELECT语法描述(见第13.2.9,“SELECT语法”)显示INTO
附近的语句结尾条款。也可以INTO在select_expr列表后立即
使用
。
INTO子句不应该用在嵌套中,SELECT因为这样
的子句
SELECT必须将其结果返回给外部上下文。
该INTO子句可以命名一个或多个变量的列表,这些变量可以是用户定义的变量,存储过程或函数参数或存储的程序局部变量。(在准备好的SELECT ... INTO
OUTFILE语句中,只允许用户定义的变量;请参见第13.6.4.2节“本地变量范围和分辨率”。)
选定的值被分配给变量。变量的数量必须与列的数量相匹配。该查询应该返回一行。如果查询不返回任何行,则会发生错误代码为1329的警告(No data),并且变量值保持不变。如果查询返回多个行,则会发生错误1172(Result consisted of
more than one row)。如果语句可能检索多行,则可以使用LIMIT
1将结果集限制为单行。
SELECT id,data INTO @x,@y FROM test.t1 LIMIT 1;
用户变量名称不区分大小写。请参见 第9.4节“用户定义的变量”。
所述的形式
的选择的行写入到一个文件中。该文件是在服务器主机上创建的,因此您必须有权使用此语法。不能成为现有的文件,这可以防止文件
和数据库表被破坏。该
系统变量控制文件名的解释。
SELECT ... INTO
OUTFILE 'file_name'SELECTFILEfile_name/etc/passwdcharacter_set_filesystem
该SELECT ... INTO
OUTFILE声明主要是为了让您快速将表转储到服务器计算机上的文本文件。如果要在除服务器主机之外的其他主机上创建生成的文件,通常无法使用,
SELECT ... INTO
OUTFILE因为无法写入相对于服务器主机文件系统的文件路径。
但是,如果MySQL客户端软件安装在远程计算机上,则可以使用客户端命令
来在客户端主机上生成该文件。
mysql -e "SELECT ..." >
file_name
如果可以使用服务器文件系统上的网络映射路径访问远程主机上文件的位置,也可以在不同于服务器主机的其他主机上创建生成的文件。在这种情况下,目标主机不需要存在 mysql(或其他MySQL客户端程序)。
SELECT ... INTO
OUTFILE是的补充
LOAD DATA
INFILE。列值被写入转换为在CHARACTER SET
子句中指定的字符集。如果不存在这样的子句,则使用binary字符集转储值。实际上,没有字符集转换。如果结果集包含多个字符集中的列,则输出数据文件也会如此,并且您可能无法正确地重新加载文件。
export_options
语句部分
的语法由FIELDS与LINES语句一起使用的LOAD DATA
INFILE语句和子句
组成
。参见第13.2.6,“LOAD DATA INFILE语法”,以获取有关信息FIELDS和
LINES条款,包括它们的默认值和允许值。
FIELDS ESCAPED BY控制如何编写特殊字符。如果该FIELDS ESCAPED BY
字符不为空,则在必要时使用该字符,以避免输出上的以下字符前面的前缀不明确:
该FIELDS ESCAPED BY字符
该FIELDS [OPTIONALLY] ENCLOSED BY
字符
FIELDS TERMINATED
BY和LINES TERMINATED BY
值
的第一个字符
ASCII NUL(零值字节;转义字符后面实际写入的是ASCII
0,而不是零值字节)
的FIELDS TERMINATED BY,ENCLOSED
BY,ESCAPED BY,或LINES
TERMINATED BY字符必须进行转义,这样就可以读取该文件回可靠。NUL通过转义ASCII码
可以更方便地查看某些寻呼机。
生成的文件不必符合SQL语法,所以不需要转义。
如果该FIELDS ESCAPED BY字符为空,则不会转义字符,NULL而是输出为NULL,而不是\N。指定一个空的转义字符可能不是一个好主意,特别是如果数据中的字段值包含刚才给出的列表中的任何字符。
以下是一个以许多程序使用的逗号分隔值(CSV)格式生成文件的示例:
SELECT a,b,a + b INTO OUTFILE'/tmp/result.txt' FIELDS TERMINATED BY','可选地''' LINES终止于'\ n' FROM test_table;
如果您使用INTO DUMPFILE而不是
INTO OUTFILEMySQL,则只向该文件写入一行,不会有任何列或行终止,也不会执行任何转义处理。如果要将BLOB值存储在文件中,这非常有用。
由服务器主机上的所有用户创建INTO OUTFILE或
INTO DUMPFILE可写入的任何文件。原因在于MySQL服务器无法创建一个文件,该文件是其运行的帐户下的用户以外的任何人拥有的文件。(你应该
永远运行mysqld的是
root,这和其他的原因。)因此,该文件必须是全球可写的,这样就可以操纵它的内容。
如果secure_file_priv
系统变量设置为非空目录名称,则要写入的文件必须位于该目录中。
在SELECT ...
INTO作为事件调度程序执行的事件一部分发生的语句的上下文中
,诊断消息(不仅是错误,还包括警告)将写入错误日志,并在Windows上写入应用程序事件日志。有关更多信息,请参见第23.4.5节“事件计划程序状态”。
MySQL支持语句部分
和多表和
语句的以下JOIN语法:
table_referencesSELECTDELETEUPDATE
table_references:escaped_table_reference[,escaped_table_reference] ...escaped_table_reference:table_reference| {OJtable_reference}table_reference:table_factor|join_tabletable_factor:tbl_name[PARTITION(partition_names)] [[AS]alias] [index_hint_list] |table_subquery[AS]alias| (table_references)join_table:table_reference[INNER | CROSS] JOINtable_factor[join_condition] |table_referenceSTRAIGHT_JOINtable_factor|table_referenceSTRAIGHT_JOINtable_factorONconditional_expr|table_reference{LEFT | RIGHT} [OUTER]加入 | NATURAL [{LEFT | RIGHT} [OUTER]] JOINtable_referencejoin_conditiontable_referencetable_factorjoin_condition: ONconditional_expr| USING(column_list)index_hint_list:index_hint[,index_hint] ...index_hint: USE {INDEX | KEY} [FOR {JOIN | ORDER BY | GROUP BY}]([index_list]) | IGNORE {INDEX | KEY} [FOR {JOIN | ORDER BY | GROUP BY}](index_list) | FORCE {INDEX | KEY} [FOR {JOIN | ORDER BY | GROUP BY}](index_list)index_list:index_name[,index_name] ...
表引用也称为联接表达式。
表引用(当它引用分区表时)可能包含一个PARTITION选项,包括逗号分隔的分区,子分区或两者的列表。该选项跟随表的名称并位于任何别名声明之前。此选项的作用是仅从列出的分区或子分区中选择行。列表中未命名的任何分区或子分区都将被忽略。有关更多信息和示例,请参见
第22.5节“分区选择”。
table_factor与标准SQL相比,在MySQL中扩展
的语法。该标准只接受table_reference,而不是一对括号内的列表。
如果table_reference项目列表中的每个逗号都等同于内部联接,则这是一个保守的扩展
。例如:
SELECT * FROM t1 LEFT JOIN(t2,t3,t4)
ON(t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)
相当于:
SELECT * FROM t1 LEFT JOIN(t2 CROSS JOIN t3 CROSS JOIN t4)
ON(t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)
在MySQL, ,JOIN,CROSS
JOIN和INNER JOIN是句法当量(它们可以彼此替换)。在标准的SQL中,它们不是等价的。INNER JOIN与ON子句一起CROSS JOIN
使用,否则使用。
通常,在仅包含内连接操作的连接表达式中可以忽略括号。MySQL也支持嵌套连接。请参见第8.2.1.7节“嵌套连接优化”。
可以指定索引提示以影响MySQL优化器如何使用索引。有关更多信息,请参见
第8.9.4节“索引提示”。优化器提示和
optimizer_switch系统变量是影响优化器使用索引的其他方式。请参见
第8.9.2节“优化器提示”和
第8.9.3节“可切换优化”。
以下列表描述了在编写联接时要考虑的一般因素:
表引用可以使用或
别名
:
tbl_name AS
alias_nametbl_name alias_name
SELECT t1.name,t2.salary FROM employee AS t1 INNER JOIN info AS t2 ON t1.name = t2.name; SELECT t1.name,t2.salary FROM employee t1 INNER JOIN info t2 ON t1.name = t2.name;
A table_subquery也被称为FROM
子句中的派生表或子查询。请参见第13.2.10.8节“派生表(FROM子句中的子查询)”。这种子查询必须包含一个别名,以便为子查询结果指定一个表名。一个简单的例子如下:
SELECT * FROM(SELECT 1,2,3)AS t1;
INNER JOIN和,
(逗号)在没有连接条件时在语义上是等价的:两者都在指定的表之间产生笛卡尔乘积(也就是说,第一个表中的每一行都连接到第二个表中的每一行)。
然而,逗号运算符的优先级低于的INNER JOIN,CROSS
JOIN,LEFT JOIN,等等。如果在存在联接条件时将逗号联接与其他联接类型混合,则可能会发生表单错误。有关处理这个问题的信息在本节后面给出。
Unknown
column 'col_name' in 'on
clause'
的conditional_expr使用
ON是可以在中可以使用的形式的任何条件表达式WHERE子句。通常,ON子句用于指定如何连接表的条件,并且
WHERE子句限制将哪些行包含在结果集中。
如果没有匹配右侧表格ON或USINGa中
右侧表格
LEFT JOIN的行,则所有列设置为的行将
NULL用于右侧表格。您可以使用这个事实来查找表中没有对应表的行:
SELECT left_tbl。* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;
本示例查找所有行中不存在left_tbl
的id值
right_tbl(也就是说,所有行都
left_tbl没有对应的行
right_tbl)。参见
第8.2.1.8节“左连接和右连接优化”。
该
子句命名两个表中必须存在的列的列表。如果表和
两者都包含列
,和
,下面加入相应的列从两个表进行比较:
USING(column_list)abc1c2c3
左连接b使用(c1,c2,c3)
的NATURAL [LEFT] JOIN两个表被定义为语义上等同于一个INNER
JOIN或一个LEFT JOIN带有
USING条款名称存在两个表中的所有列。
RIGHT JOIN类似地工作
LEFT JOIN。为了让代码可以跨数据库移植,建议您使用LEFT
JOIN而不是RIGHT JOIN。
将{ OJ ... }在联接语法描述中显示存在语法只是为了与ODBC兼容。句法中的花括号应该按照字面意思写; 它们不是在语法描述中其他地方使用的metasyntax。
SELECT left_tbl。*
FROM {OJ left_tbl LEFT OUTER JOIN right_tbl ON left_tbl.id = right_tbl.id}
WHERE right_tbl.id IS NULL;
您可以使用其他类型的连接{ OJ ...
},例如INNER JOIN或
RIGHT OUTER JOIN。这有助于与某些第三方应用程序的兼容性,但不是官方的ODBC语法。
STRAIGHT_JOIN类似于
JOIN,除了左表总是在右表之前读取。这可以用于连接优化程序以次优顺序处理表的情况(很少)。
一些加入示例:
SELECT * FROM table1,table2; SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id; SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id; SELECT * FROM table1 LEFT JOIN table2 USING(id); SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id LEFT JOIN table3 ON table2.id = table3.id;
USING根据SQL:2003标准处理
自然连接和连接(包括外部连接变体):
NATURAL没有出现连接的
冗余列。考虑这组声明:
CREATE TABLE t1(i INT,j INT); CREATE TABLE t2(k INT,j INT); INSERT INTO t1 VALUES(1,1); 插入t2值(1,1); SELECT * FROM t1 NATURAL JOIN t2; SELECT * FROM t1 JOIN t2 USING(j);
在第一条SELECT
语句中,列出j现在两个表中,因此成为连接列,因此根据标准SQL,它只能在输出中出现一次,而不是两次。同样,在第二个SELECT语句中,列
j在该USING子句中被命名,
并且应该只在输出中出现一次,而不是两次。
因此,这些语句产生这个输出:
+ ------ + ------ + ------ + | j | 我| k | + ------ + ------ + ------ + | 1 | 1 | 1 | + ------ + ------ + ------ + + ------ + ------ + ------ + | j | 我| k | + ------ + ------ + ------ + | 1 | 1 | 1 | + ------ + ------ + ------ +
根据标准SQL,发生冗余列消除和列排序,产生此显示顺序:
首先,按照它们在第一个表中出现的顺序合并两个连接表中的公共列
其次,第一个表的唯一列,它们在该表中出现的顺序
第三,第二个表格的唯一列,以便它们出现在该表格中
替换两个公共列的单个结果列是使用合并操作定义的。也就是说,对于两个
t1.a并且t2.a生成的单个连接列a被定义为a = COALESCE(t1.a, t2.a),其中:
COALESCE(x,y)=(当x不为空然后x ELSE y END时)
如果连接操作是任何其他连接,则连接的结果列由连接表的所有列的连接组成。
合并列定义的结果是,对于外连接,NULL如果两列中的一列始终存在,合并列将包含非列的值NULL。如果两列或两列都不同NULL,则两个公共列的值都相同,因此选择哪一列作为合并列的值并不重要。一种简单的方法来解释这一点,就是认为外连接的合并列由a的内部表的公共列表示JOIN。假设表t1(a, b),并
t2(a, c)具有下列内容:
t1 t2 ---- ---- 1 x 2 z 2 y 3 w
然后,对于此联接,列a包含以下值t1.a:
MySQL的> SELECT * FROM t1 NATURAL LEFT JOIN t2;
+ ------ + ------ + ------ +
| a | b | c |
+ ------ + ------ + ------ +
| 1 | x | NULL |
| 2 | y | z |
+ ------ + ------ + ------ +
相比之下,对于此连接,列a
包含的值t2.a。
MySQL的> SELECT * FROM t1 NATURAL RIGHT JOIN t2;
+ ------ + ------ + ------ +
| a | c | b |
+ ------ + ------ + ------ +
| 2 | z | y |
| 3 | w | NULL |
+ ------ + ------ + ------ +
将这些结果与其他等效查询进行比较JOIN ... ON:
MySQL的> SELECT * FROM t1 LEFT JOIN t2 ON (t1.a = t2.a);
+ ------ + ------ + ------ + ------ +
| a | b | a | c |
+ ------ + ------ + ------ + ------ +
| 1 | x | NULL | NULL |
| 2 | y | 2 | z |
+ ------ + ------ + ------ + ------ +
MySQL的> SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a = t2.a);
+ ------ + ------ + ------ + ------ +
| a | b | a | c |
+ ------ + ------ + ------ + ------ +
| 2 | y | 2 | z |
| NULL | NULL | 3 | w |
+ ------ + ------ + ------ + ------ +
甲USING子句可以改写为一个
ON用于比较对应列子句。然而,虽然USING和
ON它们相似,但它们并不完全相同。考虑以下两个查询:
左连接b使用(c1,c2,c3) a LEFT JOIN b ON a.c1 = b.c1 AND a.c2 = b.c2 AND a.c3 = b.c3
关于确定哪些行满足连接条件,两个连接在语义上是相同的。
关于确定要显示哪些列以进行
SELECT *扩展,这两个连接在语义上不是相同的。的USING而加入选择对应列的聚结的值,ON从所有表加入选择的所有列。对于USING连接,
SELECT *选择这些值:
COALESCE(a.c1,b.c1),COALESCE(a.c2,b.c2),COALESCE(a.c3,b.c3)
对于ON连接,SELECT
*选择这些值:
a.c1,a.c2,a.c3,b.c1,b.c2,b.c3
使用内部联接COALESCE(a.c1,
b.c1)与两者相同
a.c1或者b.c1因为两个列将具有相同的值。使用外连接(如LEFT JOIN),两列中的一个可以NULL。该列在结果中被省略。
一个ON子句只能引用它的操作数。
例:
CREATE TABLE t1(i1 INT); CREATE TABLE t2(i2 INT); CREATE TABLE t3(i3 INT); SELECT * FROM t1 JOIN t2 ON(i1 = i3)JOIN t3;
该语句失败并出现Unknown column 'i3' in
'on clause'错误,因为i3该列中的列t3不是该ON子句的操作数。要使连接得到处理,请按如下所示重写语句:
SELECT * FROM t1 JOIN t2 JOIN t3 ON(i1 = i3);
JOIN比逗号运算符(,)具有更高的优先级,所以连接表达式
t1, t2 JOIN t3被解释为
(t1, (t2 JOIN t3)),而不是((t1,
t2) JOIN t3)。这会影响使用ON子句的语句,
因为该子句只能引用连接的操作数中的列,而优先级会影响对这些操作数的解释。
例:
CREATE TABLE t1(i1 INT,j1 INT); CREATE TABLE t2(i2 INT,j2 INT); CREATE TABLE t3(i3 INT,j3 INT); INSERT INTO t1 VALUES(1,1); 插入t2值(1,1); 插入到t3值(1,1); SELECT * FROM t1,t2 JOIN t3 ON(t1.i1 = t3.i3);
该JOIN过逗号运算符的优先级,所以对于操作数ON
子句t2和t3。因为t1.i1不是任何一个操作数中的列,所以结果是Unknown column
't1.i1' in 'on clause'错误的。
要启用连接处理,请使用以下任一策略:
小组前两个带括号的明确表,这样的操作数ON
子句(t1, t2)和
t3:
SELECT * FROM(t1,t2)JOIN t3 ON(t1.i1 = t3.i3);
避免使用逗号运算符并JOIN改为使用
:
SELECT * FROM t1 JOIN t2 JOIN t3 ON(t1.i1 = t3.i3);
优先级相同的解释也适用于与混合逗号操作语句INNER
JOIN,CROSS JOIN,LEFT
JOIN,并且RIGHT JOIN,所有这些都具有比逗号操作符更高的优先级。
与SQL:2003标准相比,MySQL扩展是MySQL允许您限定常见(合并)列NATURAL或USING
连接,而标准不允许使用该标准。
选择 ... UNION [ALL | DISTINCT] SELECT ... [UNION [ALL | DISTINCT] SELECT ...]
UNION用于将多个SELECT
语句的结果合并到一个结果集中。
第一条
SELECT语句的列名称用作返回结果的列名称。在每个SELECT语句的相应位置列出的选定列
应具有相同的数据类型。(例如,第一条语句选择的第一列应该与其他语句选择的第一列具有相同的类型。)
如果相应SELECT列的数据类型
不匹配,则UNION结果中列的类型和长度
会考虑所有SELECT语句检索的值
。例如,请考虑以下几点:
MySQL的> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+ --------------- +
| REPEAT('a',1)|
+ --------------- +
| a |
| bbbbbbbbbb |
+ --------------- +
这些SELECT语句是正常的选择语句,但有以下限制:
缺省行为UNION是从结果中删除重复的行。DISTINCT除了缺省值外,可选
关键字不起作用,因为它还指定重复行删除。使用可选ALL关键字,重复行删除不会发生,并且结果包括所有SELECT语句的所有匹配行。
你可以混合UNION
ALL和UNION
DISTINCT在相同的查询。混合
UNION类型的处理方式使得工会在其左侧DISTINCT覆盖任何
ALL工会。甲
DISTINCT工会可以明确,通过使用来产生UNION
DISTINCT或隐式地通过使用
UNION没有以下
DISTINCT或ALL关键字。
要应用ORDER BY或LIMIT
个人SELECT,将该子句放在括号内的括号内
SELECT:
(SELECT a FROM t1 WHERE a = 10 AND B = 1 ORDER BY a LIMIT 10) 联盟 (SELECT a FROM t2 WHERE a = 11 AND B = 2 ORDER BY a LIMIT 10);
以前的MySQL版本可能允许没有括号的语句。在MySQL 5.7中,强制执行括号的要求。
ORDER BY单个SELECT语句的
使用对于
最终结果中行出现的顺序没有任何意义,因为UNION默认情况下会生成无序的一组行。因此,ORDER
BY在这个上下文中的使用通常与其结合使用
LIMIT,以便它被用来确定为其检索的所选行的子集
SELECT,即使它不一定会影响最终UNION结果中这些行的顺序
。如果ORDER
BY没有LIMIT在a中
出现SELECT,它会被优化掉,因为它无论如何都不会起作用。
要使用ORDER BY或
LIMIT子句对整个UNION结果进行排序或限制
,请将单个SELECT语句括起来并放在最后一个ORDER BY或
LIMIT之后。以下示例使用两个子句:
(SELECT a FROM t1 WHERE a = 10且B = 1) 联盟 (SELECT a FROM t2 WHERE a = 11且B = 2) 根据限制10订购;
没有括号的声明相当于刚才显示的一个加括号。
这种类型ORDER BY不能使用包含表名称的列引用(即以tbl_name。col_name
格式表示的名称
)。相反,在第一个SELECT语句中提供一个列别名
并引用该别名ORDER BY。(或者,请参阅ORDER BY使用其列位置的列,但不建议使用列位置。)
另外,如果要排序的列是别名,则该ORDER
BY子句必须引用别名,而不是列名。以下第一条语句可以工作,但第二条语句会失败,并显示
Unknown column 'a' in 'order clause'错误信息:
(SELECT a AS b FROM t)UNION(SELECT ...)ORDER BY b; (SELECT a AS b FROM t)UNION(SELECT ...)ORDER BY a;
要使UNION结果中的行由各自依次检索的行组成,请
SELECT在每个列中选择一个附加列
SELECT作为排序列,并ORDER BY在最后添加一个跟随
列SELECT:
(SELECT 1 AS sort_col,col1a,col1b,... FROM t1) 联盟 (SELECT 2,col2a,col2b,... FROM t2)ORDER BY sort_col;
要在单个SELECT结果中额外维护排序顺序
,请在ORDER BY子句中添加一个辅助列:
(SELECT 1 AS sort_col,col1a,col1b,... FROM t1) 联盟 (SELECT 2,col2a,col2b,... FROM t2)ORDER BY sort_col,col1a;
使用附加列还可以确定哪一SELECT行来自哪一
行。额外的列也可以提供其他标识信息,例如指示表名称的字符串。
UNIONORDER BY子句中具有聚合函数的查询被拒绝并出现
ER_AGGREGATE_ORDER_FOR_UNION
错误。例:
SELECT 1 AS foo UNION SELECT 2 ORDER BY MAX(1);
子查询是SELECT另一个语句中的一个语句。
支持SQL标准所需的所有子查询形式和操作,以及一些特定于MySQL的功能。
这是一个子查询的例子:
SELECT * FROM t1 WHERE column1 =(SELECT column1 FROM t2);
在这个例子中,SELECT * FROM t1 ...是
外部查询(或外部语句),并且(SELECT column1 FROM
t2)是子查询。我们说子查询嵌套在外部查询中,实际上可以将子查询嵌套在其他子查询中,达到相当深的程度。子查询必须始终出现在括号内。
子查询的主要优点是:
下面是一个示例语句,它显示了SQL标准中指定的并且在MySQL中支持的子查询语法的主要观点:
从t1删除
哪里s11>任何
(SELECT COUNT(*)/ * no hint * / FROM t2
不存在
(SELECT * FROM t3
WHERE ROW(5 * t2.s1,77)=
(SELECT 50,11 * s1 FROM t4 UNION SELECT 50,77 FROM
(SELECT * FROM t5)AS t5)));
子查询可以返回标量(单个值),单个行,单个列或表(一列或多列一列或多列)。这些称为标量,列,行和表子查询。子查询返回特定类型的结果通常只能在特定的上下文中使用,如以下各节所述。
对于可以使用子查询的语句的类型几乎没有限制。子查询可以包含许多普通的关键字或条款
SELECT可能包含:
DISTINCT,GROUP BY,
ORDER BY,LIMIT,连接,索引提示,UNION结构,注释,函数等等。
子查询的外部语句可以是任何一个:
SELECT,
INSERT,
UPDATE,
DELETE,
SET,或
DO。
在MySQL中,您无法修改表并从子查询中的同一个表中进行选择。这适用于语句,例如
DELETE,
INSERT,
REPLACE,
UPDATE,和(因为子查询可以在中使用SET子句)
LOAD DATA
INFILE。
有关优化程序如何处理子查询的信息,请参见 第8.2.2节“优化子查询,派生表和视图引用”。有关子查询使用限制的讨论,包括某些形式的子查询语法的性能问题,请参见 第C.4节“对子查询的限制”。
以最简单的形式,子查询是返回单个值的标量子查询。标量子查询是一个简单的操作数,并且几乎可以在单个列值或文字合法的任何位置使用它,并且您可以期望它具有所有操作数具有的特征:数据类型,长度,它可以指示是NULL,等等。例如:
CREATE TABLE t1(s1 INT,s2 CHAR(5)NOT NULL); INSERT INTO t1 VALUES(100,'abcde'); SELECT(SELECT s2 FROM t1);
子查询SELECT
返回一个单值('abcde'),其数据类型为CHAR5,长度为5,字符集和排序规则等同于当时有效的默认值
CREATE TABLE,并指示列中的值可以是
NULL。由标量子查询选择的值的可空性不会被复制,因为如果子查询结果为空,则结果为NULL。对于刚刚显示的子查询,如果t1是空的,结果将是NULL即使
s2是NOT NULL。
有几个上下文中不能使用标量子查询。如果语句只允许一个字面值,则不能使用子查询。例如,LIMIT需要文字整数参数,并且
LOAD DATA
INFILE需要文字串文件名。您不能使用子查询来提供这些值。
当你在下面的章节中看到包含比较斯巴达结构的例子时(SELECT column1 FROM
t1),想象你自己的代码包含更多样化和复杂的结构。
假设我们制作两个表格:
CREATE TABLE t1(s1 INT); INSERT INTO t1 VALUES(1); CREATE TABLE t2(s1 INT); 插入t2值(2);
然后执行SELECT:
SELECT(SELECT s1 FROM t2)FROM t1;
结果是2因为有一行
t2包含s1
一个值为的列2。
标量子查询可以是表达式的一部分,但要记住括号,即使子查询是为函数提供参数的操作数。例如:
SELECT UPPER((SELECT s1 FROM t1))FROM t2;
子查询最常见的用法是:
non_subquery_operandcomparison_operator(subquery)
comparison_operator这些运营商之一
在哪里:
=> <> = <= <>!= <=>
例如:
... WHERE'a'=(SELECT column1 FROM t1)
MySQL也允许这个结构:
non_subquery_operandLIKE(subquery)
有一次,子查询的唯一合法位置在比较的右侧,您仍然可以找到一些坚持这一点的旧DBMS。
以下是常见形式子查询比较的一个示例,您无法使用联接进行比较。它查找表t1中的column1
值等于表中最大值的
所有行
t2:
SELECT * FROM t1 WHERE column1 =(SELECT MAX(column2)FROM t2);
这是另一个例子,对于一个连接来说也是不可能的,因为它涉及到一个表的聚合。它查找表中t1包含在给定列中出现两次的值的所有行:
SELECT * FROM t1 AS t WHERE 2 =(SELECT COUNT(*)FROM t1 WHERE t1.id = t.id);
为了比较子查询和标量,子查询必须返回一个标量。为了比较子查询和行构造函数,子查询必须是一个行子查询,该行子查询返回与行构造函数具有相同数量值的行。请参见 第13.2.10.5节“行子查询”。
句法:
operandcomparison_operatorANY(subquery)operandIN(subquery) SOME()operandcomparison_operatorsubquery
comparison_operator这些运营商之一
在哪里:
=> <> = <= <>!=
该ANY关键字,它必须遵循一个比较操作符,表示“ 回报TRUE
如果比较TRUE的
ANY列的子查询返回的值。“例如:
SELECT s1 FROM t1 WHERE s1> ANY(SELECT s1 FROM t2);
假设表中t1
包含一行(10)。表达是
TRUE如果表t2包含
(21,14,7)因为有一个值
7在t2小于
10。表达式是
FALSE如果表t2包含
(20,10),或者表t2是空的。如果表包含
,表达式是未知的(即
NULL)。
t2(NULL,NULL,NULL)
与子查询一起使用时,该单词IN是别名= ANY。因此,这两个陈述是相同的:
SELECT s1 FROM t1 WHERE s1 = ANY(SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 IN(SELECT s1 FROM t2);
IN与= ANY表达式列表一起使用时不是同义词。
IN可以采取表达式列表,但
= ANY不能。请参见
第12.3.2节“比较函数和操作符”。
NOT IN不是别名<>
ANY,而是for <> ALL。请参见
第13.2.10.4节“使用ALL进行子查询”。
这个词SOME是别名
ANY。因此,这两个陈述是相同的:
SELECT s1 FROM t1 WHERE s1 <> ANY(SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 <> SOME(SELECT s1 FROM t2);
使用这个词SOME很少见,但这个例子显示了它为什么可能有用。对大多数人来说,英语短语“ a不等于任何b ”意味着
“ 没有b等于a ”,但这不是SQL语法的含义。语法的意思是
“ 有一些不相等的b。”使用
<> SOME,而不是有助于确保每个人都理解该查询的真正含义。
句法:
operandcomparison_operatorALL(subquery)
这个词ALL,它必须遵循一个比较操作符,表示“ 回报TRUE如果比较TRUE的ALL
列的子查询返回的值。“
例如:
SELECT s1 FROM t1 WHERE s1> ALL(SELECT s1 FROM t2);
假设表中t1
包含一行(10)。表达式是
TRUE如果表t2包含
(-5,0,+5)因为10大于全部三个值t2。表达是FALSE如果表
t2包含
(12,6,NULL,-100),因为有一个单一的值12在表t2是大于10。表达式是
未知的(即NULL)如果表t2包含
(0,NULL,1)。
最后,表达式是TRUE如果表
t2是空的。所以,下面的表达式是
TRUE当表t2是空的时候:
SELECT * FROM t1 WHERE 1> ALL(SELECT s1 FROM t2);
但是这个表达式是NULL当表
t2是空的时候:
SELECT * FROM t1 WHERE 1>(SELECT s1 FROM t2);
另外,下面的表达式是NULL
当表t2为空时:
SELECT * FROM t1 WHERE 1> ALL(SELECT MAX(s1)FROM t2);
一般来说,包含NULL
值和空表的表是
“ 边缘情况”。“在编写子查询时,请始终考虑是否考虑了这两种可能性。
NOT IN是一个别名<>
ALL。因此,这两个陈述是相同的:
SELECT s1 FROM t1 WHERE s1 <> ALL(SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 NOT IN(SELECT s1 FROM t2);
标量或列子查询返回单个值或一列值。甲行子查询是一个子查询变体返回单个行,因此可以返回多个列值。行子查询比较的合法操作符是:
=> <> = <= <>!= <=>
这里有两个例子:
SELECT * FROM t1 WHERE(col1,col2)=(SELECT col3,col4 FROM t2 WHERE id = 10); SELECT * FROM t1 WHERE ROW(col1,col2)=(SELECT col3,col4 FROM t2 WHERE id = 10);
对于这两个查询,如果表中t2包含单个行id = 10,子查询将返回单个行。如果该行有col3和
col4值等于所述
col1和col2在任何行的值t1中,WHERE
表达是TRUE和每个查询返回的那些t1行。如果t2
行col3和col4值不等于任何行的值col1和
col2值t1,则表达式为FALSE,并且查询返回空结果集。表达是
未知的(也就是说,NULL)如果子查询不产生行。如果子查询生成多行,则会发生错误,因为行子查询最多只能返回一行。
有关每个运算符如何工作以进行行比较的信息,请参见第12.3.2节“比较函数和运算符”。
表达式(1,2)和
ROW(1,2)有时称为
行构造函数。这两个是相同的。行构造函数和子查询返回的行必须包含相同数量的值。
行构造函数用于与返回两列或更多列的子查询进行比较。当子查询返回单个列时,这被认为是标量值而不是行,所以行构造函数不能用于不返回至少两列的子查询。因此,以下查询失败,出现语法错误:
SELECT * FROM t1 WHERE ROW(1)=(SELECT column1 FROM t2)
行构造函数在其他情况下是合法的。例如,以下两个语句在语义上是等价的(并且由优化器以相同的方式处理):
SELECT * FROM t1 WHERE(column1,column2)=(1,1); SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
以下查询回答请求,“ 查找表t1中也存在的
所有行t2 ”:
SELECT column1,column2,column3
从t1开始
WHERE(column1,column2,column3)IN
(SELECT column1,column2,column3 FROM t2);
有关优化程序和行构造函数的更多信息,请参见第8.2.1.18节“行构造函数表达式优化”
如果子查询返回任何行,则是
,是
。例如:
EXISTS
subqueryTRUENOT EXISTS
subqueryFALSE
SELECT column1 FROM t1 WHERE EXISTS(SELECT * FROM t2);
传统上,EXISTS子查询开头
SELECT *,但它可能与开始
SELECT 5或SELECT column1
或任何东西。MySQL SELECT在这样的子查询中忽略
列表,所以它没有区别。
对于前面的示例,如果t2包含任何行,甚至包含任何NULL值的行,则EXISTS条件为
TRUE。这实际上是一个不太可能的例子,因为[NOT] EXISTS子查询几乎总是包含相关性。以下是一些更实际的例子:
一个或多个城市有什么样的商店?
SELECT DISTINCT store_type FROM商店
哪里存在(选择* FROM cities_stores
其中cities_stores.store_type = stores.store_type);
没有城市有什么样的商店?
SELECT DISTINCT store_type FROM商店
不存在(选择* FROM cities_stores
其中cities_stores.store_type = stores.store_type);
所有城市都有什么样的商店?
SELECT DISTINCT store_type FROM存储s1
不存在(
选择*从城市不存在(
SELECT * FROM cities_stores
其中cities_stores.city = cities.city
AND cities_stores.store_type = stores.store_type));
最后一个例子是双嵌套NOT
EXISTS查询。也就是说,它在一个NOT
EXISTS子句中有一个NOT EXISTS
子句。在形式上,它回答了“ 一个城市是否存在一个不在的商店
Stores ”的问题?但是更容易说一个嵌套NOT EXISTS回答“ 是
为了所有人? ”这个问题
。”x TRUEy
甲相关子是包含要也出现在外部查询表的基准的子查询。例如:
SELECT * FROM t1
WHERE column1 = ANY(SELECT column1 FROM t2
WHERE t2.column2 = t1.column2);
注意子查询包含对一列的引用
t1,即使子查询的
FROM子句没有提到一个表
t1。因此,MySQL在子查询之外查找,并t1在外部查询中查找。
假设该表t1包含一行where
column1 = 5和column2 =
6; 与此同时,表中t2包含一行where column1 = 5和column2 =
7。简单的表达式... WHERE column1 =
ANY (SELECT column1 FROM t2)是
TRUE,但在本例中,WHERE子查询中的
子句是
FALSE(因为(5,6)不等于(5,7)),所以表达式作为一个整体FALSE。
范围规则: MySQL从内部到外部评估。例如:
SELECT column1 FROM t1 AS x
WHERE x.column1 =(SELECT column1 FROM t2 AS x
WHERE x.column1 =(SELECT column1 FROM t3
WHERE x.column2 = t3.column1));
在这个声明中,x.column2必须是表中的一列,t2因为SELECT column1
FROM t2 AS x ...重命名t2。它不是表中的列,t1因为
SELECT column1 FROM t1 ...外部查询更远。
对于子句HAVING或ORDER
BY子句,MySQL也会在外部选择列表中查找列名。
对于某些情况,相关的子查询会进行优化。例如:
valIN(key_val从tbl_name哪里选择correlated_condition)
否则,它们效率低下,可能会变慢。将查询重写为联接可能会提高性能。
相关子查询中的聚合函数可能包含外部引用,前提是该函数只包含外部引用,并且该函数不包含在另一个函数或表达式中。
派生表是SELECT语句
FROM子句中的子查询
:
SELECT ... FROM(subquery)[AS]tbl_name...
该
子句是强制性的,因为子句中的每个表都
必须有一个名称。选择列表中的任何列必须具有唯一的名称。
[AS] tbl_nameFROMsubquery
为了说明起见,假设你有这张表:
CREATE TABLE t1(s1 INT,s2 CHAR(5),s3 FLOAT);
以下是如何使用FROM
示例表在子句中使用子查询:
INSERT INTO t1 VALUES(1,'1',1.0); INSERT INTO t1 VALUES(2,'2',2.0); SELECT sb1,sb2,sb3 FROM(SELECT s1 AS sb1,s2 AS sb2,s3 * 2 AS sb3 FROM t1)AS sb WHERE sb1> 1;
结果:2, '2', 4.0。
这里是另一个例子:假设你想知道分组表中的一组总和的平均值。这不起作用:
SELECT AVG(SUM(column1))FROM t1 GROUP BY column1;
但是,此查询提供了所需的信息:
SELECT AVG(sum_column1)
FROM(SELECT SUM(column1)AS sum_column1
FROM t1 GROUP BY column1)AS t1;
请注意,子查询(sum_column1)内使用的列名在外部查询中被识别。
派生表可以返回标量,列,行或表。
派生表不能是相关的子查询,或者包含外部引用或对其他表的引用
SELECT。
优化器以这样的方式确定关于派生表的信息,使得它们的实现不会发生
EXPLAIN。请参见
第8.2.2.3节“优化派生表和视图引用”。
在某些情况下,使用
EXPLAIN
SELECT将会修改表格数据。如果外部查询访问任何表并且内部查询调用更改表的一个或多个行的存储函数,则会发生这种情况。假设在数据库中有两个表t1和
一个修改的存储函数,
如下所示创建:
t2d1f1t2
CREATE DATABASE d1;
使用d1;
CREATE TABLE t1(c1 INT);
CREATE TABLE t2(c1 INT);
CREATE FUNCTION f1(p1 INT)RETURNS INT
开始
插入t2值(p1);
返回p1;
结束;
直接在函数中引用函数
EXPLAIN
SELECT对此没有影响t2,如下所示:
MySQL的>SELECT * FROM t2;空集(0.02秒) MySQL的>EXPLAIN SELECT f1(5)\G*************************** 1. row ******************** ******* ID:1 select_type:SIMPLE 表:NULL 分区:NULL 键入:NULL possible_keys:NULL 键:NULL key_len:NULL ref:NULL 行:NULL 过滤:NULL 额外:没有使用的表 一排(0.01秒) MySQL的>SELECT * FROM t2;空集(0.01秒)
这是因为该SELECT
语句没有引用任何表,正如可以在输出结果table和Extra列中看到的那样
。这也适用于以下嵌套
SELECT:
MySQL的>EXPLAIN SELECT NOW() AS a1, (SELECT f1(5)) AS a2\G*************************** 1. row ******************** ******* ID:1 select_type:SIMPLE 表:NULL 键入:NULL possible_keys:NULL 键:NULL key_len:NULL ref:NULL 行:NULL 过滤:NULL 额外:没有使用的表 1行,1警告(0.00秒) MySQL的>SHOW WARNINGS;+ ------- + ------ + ---------------------------------- -------- + | 级别| 代码| 留言| + ------- + ------ + ---------------------------------- -------- + | 注意| 1249 | 优化过程中选择2减少| + ------- + ------ + ---------------------------------- -------- + 一排(0.00秒) MySQL的>SELECT * FROM t2;空集(0.00秒)
但是,如果外部SELECT
引用任何表,那么优化器也会在子查询中执行语句:
MySQL的>EXPLAIN SELECT * FROM t1 AS a1, (SELECT f1(5)) AS a2\G*************************** 1. row ******************** ******* ID:1 select_type:PRIMARY 表:<derived2> 分区:NULL 类型:系统 possible_keys:NULL 键:NULL key_len:NULL ref:NULL 行:1 过滤:100.00 额外:NULL *************************** 2. row ******************** ******* ID:1 select_type:PRIMARY 表格:a1 分区:NULL 键入:ALL possible_keys:NULL 键:NULL key_len:NULL ref:NULL 行:1 过滤:100.00 额外:NULL *************************** 3. row ******************** ******* ID:2 select_type:DERIVED 表:NULL 分区:NULL 键入:NULL possible_keys:NULL 键:NULL key_len:NULL ref:NULL 行:NULL 过滤:NULL 额外:没有使用的表 设置3行(0.00秒) MySQL的>SELECT * FROM t2;+ ------ + | c1 | + ------ + | 5 | + ------ + 一排(0.00秒)
这也意味着EXPLAIN
SELECT像这里显示的
语句可能需要很长时间才能执行,因为该
BENCHMARK()函数在每行中执行一次t1:
EXPLAIN SELECT * FROM t1 AS a1,(SELECT BENCHMARK(1000000,MD5(NOW())));
有一些错误仅适用于子查询。本节介绍它们。
不支持的子查询语法:
错误1235(ER_NOT_SUPPORTED_YET) SQLSTATE = 42000 消息=“此版本的MySQL尚不支持 'LIMIT&IN / ALL / ANY / SOME subquery'“
这意味着MySQL不支持以下格式的语句:
SELECT * FROM t1 WHERE s1 IN(SELECT s2 FROM t2 ORDER BY s1 LIMIT 1)
子查询中的列数不正确:
错误1241(ER_OPERAND_COL) SQLSTATE = 21000 消息=“操作数应包含1列”
在这种情况下会发生此错误:
SELECT(SELECT column1,column2 FROM t2)FROM t1;
如果目的是行比较,您可以使用返回多个列的子查询。在其他上下文中,子查询必须是标量操作数。请参见 第13.2.10.5节“行子查询”。
子查询中的行数不正确:
错误1242(ER_SUBSELECT_NO_1_ROW) SQLSTATE = 21000 消息=“子查询返回多个行”
子查询必须返回至多一行但返回多行的语句会发生此错误。考虑下面的例子:
SELECT * FROM t1 WHERE column1 =(SELECT column1 FROM t2);
如果SELECT column1 FROM t2只返回一行,则前面的查询将起作用。如果子查询返回多个行,则会发生错误1242。在这种情况下,查询应该被重写为:
SELECT * FROM t1 WHERE column1 = ANY(SELECT column1 FROM t2);
在子查询中错误地使用表:
错误1093(ER_UPDATE_TABLE_USED) SQLSTATE = HY000 消息=“你不能指定目标表'x' 在FROM子句中更新“
在下面的情况下会发生此错误,它会尝试修改表并从子查询中的同一个表中进行选择:
UPDATE t1 SET column2 =(SELECT MAX(column1)FROM t1);
您可以在UPDATE语句中使用子查询进行赋值,
因为子查询在语句UPDATE和
DELETE语句中以及在SELECT语句中都是合法的
。但是,t1对于子查询FROM子句和更新目标,您不能使用同一个表(在本例中为表
)
。
对于事务性存储引擎,子查询失败会导致整个语句失败。对于非事务性存储引擎,在遇到错误之前进行的数据修改将被保留。
开发正在进行中,所以没有长期的优化技巧是可靠的。以下列表提供了一些您可能想要玩的有趣技巧。另请参见 第8.2.2节“优化子查询,派生表和视图引用”。
使用影响子查询中行数或顺序的子查询子句。例如:
SELECT * FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2 ORDER BY column1); SELECT * FROM t1 WHERE t1.column1 IN (SELECT DISTINCT column1 FROM t2); SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 LIMIT 1);
将联接替换为子查询。例如,试试这个:
SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN( SELECT column1 FROM t2);
取而代之的是:
SELECT DISTINCT t1.column1 FROM t1,t2 WHERE t1.column1 = t2.column1;
一些子查询可以转换为连接,以便与不支持子查询的旧版MySQL兼容。但是,在某些情况下,将子查询转换为连接可能会提高性能。请参见 第13.2.10.11节“将子查询重写为连接”。
将子句从外部移动到子查询中。例如,使用这个查询:
SELECT * FROM t1 WHERE s1 IN(SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
而不是这个查询:
SELECT * FROM t1 WHERE s1 IN(SELECT s1 FROM t1)或s1 IN(SELECT s1 FROM t2);
再举一个例子,使用这个查询:
SELECT(SELECT column1 + 5 FROM t1)FROM t2;
而不是这个查询:
SELECT(SELECT column1 FROM t1)+ 5 FROM t2;
使用行子查询而不是相关的子查询。例如,使用这个查询:
SELECT * FROM t1 WHERE(column1,column2)IN(SELECT column1,column2 FROM t2);
而不是这个查询:
SELECT * FROM t1
WHERE EXISTS(SELECT * FROM t2 WHERE t2.column1 = t1.column1
AND t2.column2 = t1.column2);
使用NOT (a = ANY (...))而不是
a <> ALL (...)。
使用而不是。
x = ANY (table containing
(1,2))x=1 OR
x=2
使用= ANY而不是
EXISTS。
对于总是返回一行的不相关的子查询,
IN总是慢于
=。例如,使用这个查询:
SELECT * FROM t1 在哪里t1。col_name=(SELECT a FROM t2 WHERE b =some_const);
而不是这个查询:
SELECT * FROM t1 在哪里t1。col_nameIN(从b选择一个从t2的b =some_const);
这些技巧可能会导致程序变得更快或更慢。使用像这个BENCHMARK()函数一样的MySQL工具
,你可以了解在你自己的情况下有什么帮助。参见
第12.14节“信息功能”。
MySQL本身所做的一些优化是:
MySQL只执行一次不相关的子查询。用于
EXPLAIN确保给定子查询确实不相关。
MySQL的重写IN,
ALL,ANY,和
SOME子查询,企图采取的是,在子查询选择列表中的列索引的可能性优势。
MySQL用索引查找函数替换以下表单的子查询,该函数
EXPLAIN描述为特殊的连接类型(unique_subquery或
index_subquery):
... IN(indexed_column从single_table...中选择)
MySQL使用涉及MIN()或
的表达式增强了以下表单的表达式MAX(),除非包含
NULL值或空集:
value{ALL | ANY | SOME} {> | <| > = | <=}(uncorrelated subquery)
例如,这个WHERE条款:
WHERE 5> ALL(SELECT x FROM t)
可能会像这样被优化器处理:
WHERE 5>(SELECT MAX(x)FROM t)
另请参见 MySQL内部:MySQL如何转换子查询。
有时候还有其他方法来测试一组值中的成员资格,而不是使用子查询。此外,在某些情况下,不仅可以在没有子查询的情况下重写查询,但使用其中一些技术而不是使用子查询可能更有效。其中之一是
IN()构造:
例如,这个查询:
SELECT * FROM t1 WHERE id IN(SELECT id FROM t2);
可以改写为:
SELECT DISTINCT t1。* FROM t1,t2 WHERE t1.id = t2.id;
查询:
SELECT * FROM t1 WHERE id NOT IN(SELECT id FROM t2); SELECT * FROM t1 WHERE NOT EXISTS(SELECT id FROM t2 WHERE t1.id = t2.id);
可以改写为:
SELECT table1。* FROM table1 LEFT JOIN table2 ON table1.id = table2.id WHERE table2.id IS NULL;
A LEFT [OUTER] JOIN可以比等效的子查询更快,因为服务器可能能够更好地优化它 - 这并非特定于MySQL服务器的事实。在SQL-92之前,外连接不存在,所以子查询是做某些事情的唯一方法。今天,MySQL服务器和许多其他现代数据库系统提供了广泛的外部联接类型。
MySQL服务器支持多表
DELETE语句,这些语句可用于根据一个表中的信息甚至同时从多个表中有效地删除行。多表
UPDATE语句也被支持。请参见第13.2.2节“DELETE语法”和
第13.2.11节“UPDATE语法”。
UPDATE 是修改表中的行的DML语句。
单表语法:
UPDATE [LOW_PRIORITY] [IGNORE]table_referenceSETassignment_list[WHEREwhere_condition] [ORDER BY ...] [限制row_count]value: {expr| 默认}assignment:col_name=valueassignment_list:assignment[,assignment] ...
多表语法:
UPDATE [LOW_PRIORITY] [IGNORE]table_referencesSETassignment_list[WHEREwhere_condition]
对于单表语法,该
UPDATE语句使用新值更新指定表中现有行的列。该
SET条款指出要修改哪些列以及应该给出哪些值。每个值都可以作为表达式给出,或者将关键字DEFAULT明确地设置为默认值。该
WHERE子句如果给出,则指定标识要更新哪些行的条件。没有
WHERE子句,所有行都被更新。如果ORDER BY指定了
子句,则按照指定的顺序更新行。该
LIMIT子句对可更新的行数设置了限制。
对于多表语法,
UPDATE更新在其中命名的每个表中的行table_references满足条件。即使匹配条件多次,每个匹配行也会更新一次。对于多表语法,
ORDER BY并且LIMIT不能使用。
对于分区表,此语句的单个单表格和多个表格都支持将
PARTITION选项用作表引用的一部分。此选项将获取一个或多个分区或子分区(或两者)的列表。只有列出的分区(或子分区)才会检查匹配项,而不在这些分区或子分区中的任何分区中的行不会更新,无论它是否满足要求where_condition。
与使用时的情况PARTITION有一个
INSERT或
REPLACE声明,一个非常有效的UPDATE ... PARTITION声明被认为是成功的,即使在列出的分区(或子)没有行匹配
where_condition。
有关更多信息和示例,请参见 第22.5节“分区选择”。
where_condition是一个表达式,每个要更新的行的值都为true。有关表达式语法,请参见第9.5节“表达式语法”。
table_references并
where_condition按照第13.2.9节“SELECT语法”中的说明进行指定。
您UPDATE只需要在UPDATE
实际更新中引用的列的权限。您只需要SELECT读取但未修改的任何列的
权限。
该UPDATE语句支持以下修饰符:
使用LOW_PRIORITY修饰符时,UPDATE延迟的执行被延迟,直到没有其他客户端正在从表中读取。这会影响只使用表级锁只存储引擎(例如
MyISAM,MEMORY和
MERGE)。
使用IGNORE修饰符,即使在更新期间发生错误,update语句也不会中止。不会更新在唯一键值上出现重复键冲突的行。行更新为将导致数据转换错误的值更新为最接近的有效值。有关更多信息,请参阅
IGNORE关键字和严格SQL模式的比较。
UPDATE IGNORE
语句(包括具有ORDER BY
子句的语句)被标记为不安全的基于语句的复制。(这是因为更新行的顺序决定忽略哪些行)。当使用基于语句的模式时,这些语句会在错误日志中产生警告,并在使用MIXED模式时使用基于行的格式写入二进制日志
。(错误#11758262,错误#50439)有关更多信息,请参见
第16.2.1.3节“确定二进制日志中安全和不安全的语句”。
如果从表中访问要更新的表UPDATE中的列,请使用列的当前值。例如,以下语句设置
col1为比当前值多一个:
UPDATE t1 SET col1 = col1 + 1;
以下语句中的第二个分配设置
col2为当前(更新)的
col1值,而不是原始
col1值。结果是,
col1并col2具有相同的价值。此行为不同于标准SQL。
UPDATE t1 SET col1 = col1 + 1,col2 = col1;
单表UPDATE分配通常从左到右进行评估。对于多表更新,不保证分配按任何特定顺序执行。
如果您将列设置为当前所具有的值,MySQL会注意到这一点并且不会更新它。
如果更新已NOT
NULL设置为已声明的列,则在NULL严格SQL模式启用时会发生错误; 否则,该列将设置为列数据类型的隐式默认值,并且警告计数会递增。隐式默认值是
0数字类型,字符串类型是空字符串(''),日期和时间类型是
“ 零 ”值。请参见
第11.7节“数据类型默认值”。
如果生成的列被明确更新,则唯一允许的值是DEFAULT。有关生成列的信息,请参见
第13.1.18.8节“CREATE TABLE和Generated Columns”。
UPDATE返回实际更改的行数。在
mysql_info()C API函数返回被匹配和更新的行数,并在发生警告的数量
UPDATE。
您可以使用来限制该范围。一个
子句是一个行匹配的限制。只要发现满足该子句的行,
该语句就会停下来
,而不管它们是否真的发生了变化。
LIMIT
row_countUPDATELIMITrow_countWHERE
如果UPDATE语句包含一个
ORDER BY子句,那么这些行将按照该子句指定的顺序更新。这在某些情况下可能会有用,否则可能会导致错误。假设一个表t包含一个id
具有唯一索引的列。以下语句可能会因重复键错误而失败,具体取决于更新行的顺序:
UPDATE t SET id = id + 1;
例如,如果该表在id列中包含1和2,
并且在2更新为3之前1更新为2,则会发生错误。为避免此问题,请添加一个
ORDER BY子句,以便id在具有较小值的行之前更新具有较大值的行
:
UPDATE t SET id = id + 1 ORDER BY id DESC;
您也可以执行UPDATE
覆盖多个表的操作。但是,您不能使用
多表ORDER BY或LIMIT使用多表UPDATE。该
table_references子句列出了参与连接的表。其语法在
第13.2.9.2节“JOIN语法”中描述。这里是一个例子:
UPDATE items,month SET items.price = month.price WHERE items.id = month.id;
上例显示了使用逗号运算符的内连接,但多表UPDATE
语句可以使用语句中允许的任何类型的连接
SELECT,例如
LEFT JOIN。
如果您使用UPDATE
涉及InnoDB存在外键约束的表的多表语句,则MySQL优化器可能会按照与其父/子关系不同的顺序来处理表。在这种情况下,语句失败并回滚。相反,更新单个表并依赖提供的
ON UPDATE功能
InnoDB来相应地修改其他表。请参见
第14.8.1.6节“InnoDB和FOREIGN KEY约束”。
您无法更新表并从子查询中的相同表中进行选择。
一个UPDATE使用的存储引擎,诸如分区表MyISAM,其使用表级锁锁只有那些含有匹配的行的分区UPDATE声明
WHERE子句,只要没有表分区的列被更新的。(对于InnoDB使用行级锁定的存储引擎
,不会发生分区锁定。)有关更多信息,请参见
第22.6.4节“分区和锁定”。
MySQL支持通过语句,如本地事务(一个给定的客户端会话内)
SET autocommit,
START TRANSACTION,
COMMIT,和
ROLLBACK。请参见
第13.3.1节“START TRANSACTION,COMMIT和ROLLBACK语法”。XA事务支持还使MySQL能够参与分布式事务。请参见
第13.3.7节“XA事务”。
开始交易
[ transaction_characteristic[,transaction_characteristic] ...]
transaction_characteristic:
与一致的快照
| 读写
| 只读
BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET autocommit = {0 | 1}
这些陈述提供了对交易使用的控制 :
START TRANSACTION或
BEGIN开始新的交易。
COMMIT 提交当前事务,使其更改永久化。
ROLLBACK 回滚当前事务,取消其更改。
SET autocommit 禁用或启用当前会话的默认自动提交模式。
默认情况下,MySQL在启用自动提交模式的情况下运行 。这意味着只要执行更新(修改)表的语句,MySQL就会将更新存储在磁盘上以使其永久保存。更改无法回滚。
要为单个系列语句隐式禁用自动提交模式,请使用以下START TRANSACTION
语句:
开始交易; SELECT @A:= SUM(salary)FROM table1 WHERE type = 1; UPDATE table2 SET summary = @ WHERE type = 1; 承诺;
与START TRANSACTION,自动提交保持禁用,直到您用COMMIT或结束交易
ROLLBACK。自动提交模式然后恢复到之前的状态。
START TRANSACTION允许一些控制交易特征的修饰符。要指定多个修饰符,请用逗号分隔它们。
该WITH CONSISTENT SNAPSHOT修正开始一致读取存储引擎,能够它。这仅适用于InnoDB。效果与从任何
表格发出a START TRANSACTION
后跟a 相同。请参见
第14.5.2.3节“一致性非锁定读取”。该修改不改变当前的事务
隔离级别,所以它提供了一个一致的快照仅在当前隔离级别是一个允许连续读取。唯一允许一致读取的隔离级别是
。对于所有其他隔离级别,SELECTInnoDBWITH
CONSISTENT SNAPSHOTREPEATABLE READWITH CONSISTENT
SNAPSHOT子句被忽略。从MySQL 5.7.2开始,当WITH CONSISTENT
SNAPSHOT子句被忽略时会产生警告。
在READ WRITE与READ
ONLY修饰符设置事务访问模式。他们允许或禁止更改交易中使用的表格。该READ ONLY限制可防止事务修改或锁定对其他事务可见的事务性和非事务性表; 该事务仍然可以修改或锁定临时表。
InnoDB当事务已知为只读时,
MySQL可为表上的查询启用额外的优化
。指定READ ONLY
可确保在只读状态无法自动确定的情况下应用这些优化。有关更多信息,请参见
第8.5.3节“优化InnoDB只读事务”。
如果未指定访问模式,则应用默认模式。除非默认值已被更改,否则它是可读写的。它不允许同时指定READ WRITE
,并READ ONLY在同一语句。
在只读模式下,仍然可以TEMPORARY使用DML语句更改使用关键字创建的表。正如永久表一样,不允许使用DDL语句进行更改。
有关事务访问模式的更多信息,包括更改默认模式的方法,请参见 第13.3.6节“SET TRANSACTION语法”。
如果read_only启用了系统变量,则显式启动事务
START TRANSACTION READ WRITE需要
SUPER特权。
许多用于编写MySQL客户端应用程序(如JDBC)的API提供了自己的方法来启动可以(有时应该)使用而不是START TRANSACTION从客户端发送语句的事务
。有关更多信息,请参阅第27章,连接器和API或API的文档。
要显式禁用自动提交模式,请使用以下语句:
SET autocommit = 0;
通过将该autocommit变量设置为零来禁用自动提交模式后
,对事务安全表(例如那些用于InnoDB或的
NDB)的更改
不会立即生效。您必须使用COMMIT将更改存储到磁盘或ROLLBACK忽略更改。
autocommit是一个会话变量,必须为每个会话设置。要为每个新连接禁用自动提交模式,请参见第5.1.5节“服务器系统变量”中的autocommit系统变量
描述
。
BEGIN并BEGIN WORK作为START TRANSACTION启动事务的别名受支持。START TRANSACTION是标准的SQL语法,是启动临时事务的推荐方式,并且允许BEGIN
没有的修饰符。
该BEGIN语句与使用BEGIN启动BEGIN ... END
复合语句的关键字
不同
。后者不会开始交易。请参见
第13.6.1节“BEGIN ... END复合语句语法”。
在所有存储的程序(存储过程和函数,触发器和事件)中,解析器将BEGIN
[WORK]视为BEGIN ...
END块的开始
。在这种情况下开始一个交易
START
TRANSACTION。
可选WORK关键字COMMIT和和ROLLBACK,CHAIN以及和RELEASE
子句一样受支持
。CHAIN和RELEASE
可用于在事务完成额外控制。completion_type
系统变量的值决定了默认的完成行为。请参见
第5.1.5节“服务器系统变量”。
该AND CHAIN子句在当前结束时立即开始新事务,并且新事务与刚刚结束的事务具有相同的隔离级别。新事务也使用与刚刚终止的事务相同的访问模式(READ
WRITE或READ ONLY)。该RELEASE子句导致服务器在终止当前事务后断开当前客户端会话。包括
NO关键字抑制CHAIN
或RELEASE完成,如果completion_type系统变量被设置为默认导致链接或发布完成,这可能很有用。
开始一个事务会导致任何未决的事务被提交。有关更多信息,请参见第13.3.3节“导致隐式提交的语句”。
开始一个事务也会导致获取的表锁
LOCK TABLES被释放,就好像你已经执行了一样
UNLOCK
TABLES。开始一个事务不会释放一个全局读取锁FLUSH TABLES
WITH READ LOCK。
为获得最佳结果,应仅使用由单个事务安全存储引擎管理的表执行事务。否则,可能会出现以下问题:
如果您使用来自多个事务安全存储引擎(如InnoDB)的表,并且事务隔离级别不是
SERIALIZABLE,则有可能当一个事务提交时,使用相同表的另一个正在进行的事务将仅看到一些更改第一笔交易。也就是说,混合引擎无法保证事务的原子性,并且可能导致不一致。(如果混合引擎事务不频繁,您可以根据需要使用
SET
TRANSACTION ISOLATION LEVEL隔离级别设置SERIALIZABLE每个事务的基础级别。)
如果您在事务中使用不是事务安全的表,则无论自动提交模式的状态如何,对这些表的更改都会立即存储。
如果ROLLBACK
在更新事务中的非事务表后发出
语句,
ER_WARNING_NOT_COMPLETE_ROLLBACK
则会发生警告。对事务安全表的更改会回滚,但不会更改为非事务安全表。
每个事务都存储在一个块中的二进制日志中
COMMIT。回滚的事务不记录。(例外:对非事务表的修改不能被回滚,如果回退的事务包括对非事务表的修改,则整个事务ROLLBACK
在最后用一个语句记录,
以确保对非事务表的修改被复制。)参见
Section 5.4.4,“二进制日志”。
您可以更改SET TRANSACTION语句事务的隔离级别或访问模式。请参见第13.3.6节“SET TRANSACTION语法”。
回滚可能是一种缓慢的操作,可能在用户没有明确要求(例如,发生错误时)时隐式发生。因此,SHOW
PROCESSLIST显示Rolling back在State会话列中,不仅用于显式回滚,
ROLLBACK
还用于隐式回滚。
在MySQL 5.7, ,BEGIN,
COMMIT和ROLLBACK不受--replicate-do-db
或--replicate-ignore-db规则。
一些语句不能回滚。通常,这些包括数据定义语言(DDL)语句,如创建或删除数据库的语句,创建,删除或更改表或存储例程的语句。
你应该设计你的交易不包括这样的陈述。如果您在一个无法回滚的事务中发出一个语句,然后另一个语句以后失败,那么在这种情况下,通过发出一个ROLLBACK
语句就无法回滚事务的全部效果
。
本节中列出的语句(及其任何同义词)隐含地结束当前会话中的任何活动事务,就像您COMMIT在执行语句之前完成了一样。
大多数这些语句在执行后也会导致隐式提交。目的是在它自己的特殊事务中处理每个这样的语句,因为它无论如何都不能被回滚。事务控制和锁定语句是例外情况:如果在执行之前发生隐式提交,则在执行之后不会发生另一个。
定义或修改数据库对象的数据定义语言(DDL)语句。
ALTER DATABASE
... UPGRADE DATA DIRECTORY NAME,
ALTER EVENT,
ALTER PROCEDURE,
ALTER SERVER,
ALTER TABLE,
ALTER VIEW,
CREATE DATABASE,
CREATE EVENT,
CREATE INDEX,
CREATE PROCEDURE,
CREATE SERVER,
CREATE TABLE,
CREATE TRIGGER,
CREATE VIEW,
DROP DATABASE,
DROP EVENT,
DROP INDEX,
DROP PROCEDURE,
DROP SERVER,
DROP TABLE,
DROP TRIGGER,
DROP VIEW,
INSTALL PLUGIN(如MySQL的5.7.6的), ,RENAME TABLE,
TRUNCATE TABLE(
UNINSTALL PLUGIN如MySQL的5.7.6的)。
ALTER FUNCTION,
CREATE FUNCTION并且
DROP FUNCTION在与存储函数一起使用时也会导致隐式提交,但与用户定义的函数不同。(ALTER
FUNCTION只能用于存储的功能。)
CREATE TABLE而
DROP TABLE如果语句不提交事务TEMPORARY
时使用的关键字。(这不适用于临时表上的其他操作,例如ALTER
TABLE和CREATE
INDEX,这会导致提交。)但是,虽然没有发生隐式提交,但语句也不会回滚,这意味着使用此类语句会导致事务性原子性被违反。例如,如果您使用CREATE
TEMPORARY TABLE然后回滚事务,则该表仍然存在。
该CREATE TABLE报表
InnoDB被作为单个交易进行处理。这意味着ROLLBACK
来自用户的a
不会撤销CREATE
TABLE用户在该事务期间所做的语句。
CREATE TABLE ...
SELECT在创建非临时表时,会在执行语句之前和之后导致隐式提交。(没有提交发生CREATE TEMPORARY TABLE
... SELECT。)
隐式使用或修改mysql数据库中的表的语句。
ALTER USER,
CREATE USER,
DROP USER,
GRANT,
RENAME USER,
REVOKE,
SET PASSWORD。
事务控制和锁定语句。
BEGIN,
LOCK TABLES,SET
autocommit = 1(如果该值不是1), ,
。
START
TRANSACTION
UNLOCK
TABLES
UNLOCK
TABLES仅在当前锁定了任何表LOCK
TABLES以获取非事务性表锁的情况下才提交事务。UNLOCK
TABLES后续不会发生提交,FLUSH TABLES
WITH READ LOCK因为后一条
语句不会获取表级锁。
事务不能嵌套。这是在您发出START
TRANSACTION语句或其同义词之一时为任何当前事务执行的隐式提交的结果。
当事务处于ACTIVE状态时,导致隐式提交的语句不能用于XA事务中
。
该BEGIN
语句与使用BEGIN
启动BEGIN ...
END复合语句的关键字
不同。后者不会导致隐式提交。请参见第13.6.1节“BEGIN ... END复合语句语法”。
数据加载语句。
LOAD DATA
INFILE。
LOAD DATA
INFILE只会为使用NDB存储引擎的表进行隐式提交。
行政声明。
ANALYZE TABLE,
CACHE INDEX,
CHECK TABLE,
FLUSH,
LOAD INDEX INTO
CACHE,OPTIMIZE
TABLE,REPAIR TABLE,
RESET。
复制控制语句。START
SLAVE,STOP SLAVE,
RESET SLAVE,
CHANGE MASTER TO。
SAVEPOINTidentifierROLLBACK [WORK]到[SAVEPOINT]identifierRELEASE SAVEPOINTidentifier
InnoDB支持SQL语句
SAVEPOINT,
ROLLBACK TO
SAVEPOINT,
RELEASE
SAVEPOINT和可选WORK
关键字
ROLLBACK。
该SAVEPOINT语句设置名称为的命名事务保存点
identifier。如果当前事务具有名称相同的保存点,则旧的保存点将被删除并设置一个新的保存点。
该ROLLBACK TO
SAVEPOINT语句将事务回滚到指定的保存点而不终止事务。保存点被设置后,当前事务对行所做的修改会撤消在回退,但InnoDB不
不释放被保存点后存储在内存中的行锁。(对于新插入的行,锁定信息由存储在该行中的事务标识携带;该锁没有单独存储在内存中,在这种情况下,行锁定在撤消中释放)。晚于指定保存点的时间将被删除。
如果ROLLBACK TO
SAVEPOINT语句返回以下错误,则表示不存在具有指定名称的保存点:
错误1305(42000):SAVEPOINT identifier不存在
该RELEASE
SAVEPOINT语句从当前事务的一组保存点中删除指定的保存点。没有提交或回滚发生。如果保存点不存在则为错误。
当前事务的所有保存点都会被删除,如果您执行了一个COMMIT,或者
ROLLBACK那个没有命名保存点。
当调用存储函数或激活触发器时,将创建新的保存点级别。以前级别的保存点不可用,因此不会与新级别的保存点冲突。当函数或触发器终止时,它所创建的任何保存点都会被释放,并恢复以前的保存点级别。
LOCK TABLES
tbl_name[[AS] alias] lock_type
[,tbl_name[[AS] alias] lock_type] ...
lock_type:
读[本地]
| [LOW_PRIORITY]写入
解锁表
MySQL允许客户端会话明确获取表锁,以便与其他会话协作访问表,或者防止其他会话在会话需要对其进行独占访问期间修改表。会话只能为自己获取或释放锁。一个会话无法获取另一个会话的锁定或另一个会话持有的释放锁定。
更新表格时,可以使用锁来模拟事务或获得更多速度。本节后面将对此进行更详细的说明。
LOCK TABLES显式获取当前客户端会话的表锁。可以为基表或视图获取表锁。您必须拥有该
LOCK TABLES特权,并且SELECT每个对象的
特权才能被锁定。
对于视图锁定,LOCK TABLES将视图中使用的所有基表添加到要锁定的一组表并将其自动锁定。如果LOCK TABLES使用显式锁定
表,则触发器中使用的任何表也会隐式锁定,如
第13.3.5.2节“锁定表和触发器”中所述。
UNLOCK
TABLES显式释放当前会话保存的任何表锁。LOCK TABLES
在获取新锁之前,隐式释放由当前会话持有的任何表锁。
另一个用途
UNLOCK
TABLES是释放与该FLUSH TABLES WITH READ LOCK
语句一起获取的全局读锁,这使您可以锁定所有数据库中的所有表。请参见第13.7.6.3节“FLUSH语法”。(如果您拥有可以及时拍摄快照的文件系统(如Veritas),则这是一种非常方便的备份方式。)
表锁只能防止其他会话不适当的读取或写入。持有WRITE
锁的会话可以执行诸如DROP TABLE或的
表级操作
TRUNCATE TABLE。对于会话持有READ锁,DROP
TABLE并且TRUNCATE TABLE
操作是不允许的。
以下讨论仅适用于非TEMPORARY表格。LOCK
TABLES允许(但忽略)
TEMPORARY表格。该表可以通过创建该表的会话自由访问,无论其他锁可能有效。不需要锁定,因为没有其他会话可以看到表格。
有关其他使用条件LOCK TABLES以及有效时无法使用的
语句的信息LOCK TABLES,请参见第13.3.5.3节“表锁定限制和条件”
锁定采集规则
要获取当前会话中的表锁,请使用该
LOCK TABLES语句。以下锁定类型可用:
READ [LOCAL] 锁:
持有锁的会话可以读取表(但不能写入)。
多个会话可以同时获取READ表的锁定。
其他会话可以在不明确获取READ锁的情况下读取表。
该LOCAL修改使不冲突的
INSERT其他会话语句(并发插入),而持有锁来执行。(请参见第8.11.3节“并发插入”)。但是,READ LOCAL如果要在持有锁的同时使用服务器外部的进程来操作数据库,
则不能使用它。对于InnoDB
表格,READ LOCAL与之相同
READ。
[LOW_PRIORITY] WRITE 锁:
持有锁的会话可以读取和写入表。
只有持有该锁的会话才能访问该表。在锁定被释放之前,其他任何会话都不能访问它。
在保持锁定的情况下锁定其他会话对表格的请求
WRITE。
该LOW_PRIORITY修饰符无效。在以前的MySQL版本中,它会影响锁定行为,但这不再成立。它现在已被弃用,其使用会产生警告。改为使用WRITE而
LOW_PRIORITY不是。
如果LOCK TABLES语句必须等待由于任何表上的其他会话所持有的锁,则它会阻塞,直到可以获取所有锁。
需要锁定的会话必须在单个LOCK TABLES
语句中获取它需要的所有锁定。当这样获得的锁被保持时,会话只能访问锁定的表。例如,在以下语句序列中,尝试访问时发生错误,
t2因为它未在LOCK TABLES语句中锁定
:
mysql>LOCK TABLES t1 READ;mysql>SELECT COUNT(*) FROM t1;+ ---------- + | COUNT(*)| + ---------- + | 3 | + ---------- + MySQL的>SELECT COUNT(*) FROM t2;错误1100(HY000):表't2'没有用LOCK TABLES锁定
INFORMATION_SCHEMA数据库中的
表格是一个例外。即使在会话持有表锁的情况下,也可以在不明确锁定的情况下访问它们
LOCK TABLES。
您无法在使用相同名称的单个查询中多次引用锁定的表。改为使用别名,并为表和每个别名获取一个单独的锁:
mysql>LOCK TABLE t WRITE, t AS t1 READ;mysql>INSERT INTO t SELECT * FROM t;错误1100:表't'未锁定LOCK TABLES MySQL的>INSERT INTO t SELECT * FROM t AS t1;
第一个错误发生,
INSERT因为对于锁定的表有两个同名的引用。第二个
INSERT成功,因为对表的引用使用不同的名称。
如果您的语句通过别名引用表,则必须使用相同的别名锁定表。没有指定别名就无法锁定表:
mysql>LOCK TABLE t READ;mysql>SELECT * FROM t AS myalias;错误1100:表'myalias'没有锁定LOCK TABLES
相反,如果您使用别名锁定表,则必须在使用该别名的语句中引用它:
mysql>LOCK TABLE t AS myalias READ;mysql>SELECT * FROM t;错误1100:表't'未锁定LOCK TABLES MySQL的>SELECT * FROM t AS myalias;
WRITE锁通常比READ锁具有更高的优先级,
以确保尽快处理更新。这意味着如果一个会话获得一个
READ锁,然后另一个会话请求一个
WRITE锁,那么后续的READ
锁请求会一直等到请求该WRITE锁的会话
获得该锁并释放它为止。
LOCK TABLES 获取锁定如下:
按照内部定义的顺序对所有表进行排序。从用户的角度来看,这个订单是不确定的。
如果要使用读取锁定和写入锁定来锁定表格,请在读取锁定请求之前放置写入锁定请求。
一次锁定一个表,直到会话获得所有锁定。
该策略确保表锁定是无死锁的。
LOCK TABLES或者UNLOCK
TABLES,当应用于分区表时,始终锁定或解锁整个表; 这些语句不支持分区锁修剪。请参见
第22.6.4节“分区和锁定”。
锁定释放规则
当一个会话持有的表锁被释放时,它们全部被同时释放。会话可以显式释放它的锁,或者锁可以在某些条件下隐式释放。
会话可以显式释放它的锁
UNLOCK
TABLES。
如果会话发出LOCK
TABLES语句以在已经持有锁的情况下获取锁,则在授予新锁之前,它的现有锁将隐式释放。
如果一个会话开始一个事务(例如,with
START
TRANSACTION),UNLOCK
TABLES则执行一个隐式
操作,这会导致释放现有的锁。(有关表锁定和事务之间交互的其他信息,请参见
第13.3.5.1节“表锁定和事务的交互”。)
如果客户端会话的连接终止,无论是正常还是异常,服务器都会隐式释放会话持有的所有表锁(事务性和非事务性)。如果客户端重新连接,锁定将不再有效。另外,如果客户端有一个活动事务,服务器在断开连接时回滚事务,并且如果发生重新连接,则新的会话从启用自动提交开始。出于这个原因,客户可能希望禁用自动重新连接。有了自动重新连接,如果发生重新连接,客户端将不会收到通知,但任何表锁或当前事务都将丢失。在禁用自动重新连接的情况下,如果连接断开,则发出下一个语句时会发生错误。客户端可以检测到错误并采取适当的措施,例如重新获取锁或重做交易。看到 第27.8.20节“C API自动重新连接控制”。
如果您ALTER TABLE在锁定的桌子上使用,它可能会解锁。例如,如果您尝试第二次ALTER TABLE
操作,则结果可能是错误的。要处理这个问题,请在第二次更改之前再次锁定表格。另请参见
第B.5.6.1节“ALTER TABLE的问题”。
Table
'tbl_name' was not locked with LOCK
TABLES
LOCK TABLES并
UNLOCK
TABLES与交易的使用互动如下:
LOCK TABLES 不是事务安全的并且在试图锁定表之前暗中提交任何活动事务。
UNLOCK
TABLES隐式地提交任何活动的事务,但只有在LOCK TABLES已经用于获取表锁的情况下。例如,在下面的一组语句中,
UNLOCK
TABLES释放全局读锁但不提交事务,因为没有表锁有效:
带读锁的平板电脑; 开始交易; 选择 ... ; 解锁表;
开始一个事务(例如,
START
TRANSACTION)隐式提交任何当前事务并释放现有的表锁。
FLUSH TABLES WITH READ LOCK
获得全局读锁定,而不是表锁,所以它不会受到相同的行为
LOCK TABLES,并
UNLOCK
TABLES相对于表锁定和隐式的提交。例如,
START
TRANSACTION不释放全局读锁。请参见第13.7.6.3节“FLUSH语法”。
其他隐式导致事务提交的语句不释放现有的表锁。有关这些语句的列表,请参见第13.3.3节“导致隐式提交的语句”。
使用LOCK
TABLES和
UNLOCK
TABLES使用事务表(例如
InnoDB表)的正确方法是使用SET autocommit = 0(not
START
TRANSACTION)开头事务,然后在显式提交事务之前LOCK
TABLES不要调用它
UNLOCK
TABLES。例如,如果您需要写入表格
t1并从表格中读取
t2,则可以这样做:
SET autocommit = 0;
锁定表t1写,t2读,...;
... do something with tables t1 and t2 here ...
承诺;
解锁表;
当你调用时LOCK TABLES,
InnoDB内部使用它自己的表锁,并且MySQL使用它自己的表锁。
InnoDB在下次提交时释放内部表锁,但是为了释放其表锁,MySQL必须调用
UNLOCK
TABLES。你不应该有
autocommit = 1,因为然后InnoDB在调用之后立即释放它的内部表锁LOCK
TABLES,并且死锁很容易发生。
InnoDB如果autocommit =
1为了帮助旧应用程序避免不必要的死锁,根本不会获取内部表锁。
ROLLBACK
不释放表锁。
如果您使用显式锁定LOCK
TABLES表,则触发器中使用的任何表也会隐式锁定:
这些锁与在LOCK
TABLES声明中明确获取的时间相同。
在触发器中使用的表上的锁定取决于该表是否仅用于读取。如果是这样,读锁就足够了。否则,使用写入锁定。
如果某个表被显式锁定以供读取
LOCK TABLES,但由于它可能在触发器内被修改而需要被锁定以进行写入,所以采用写入锁定而不是读取锁定。(也就是说,由于表在触发器中出现而需要隐式写锁,因此会导致显式读锁定请求将表转换为写锁请求。)
假设您锁定了两个表,t1并
t2使用以下语句:
锁定表t1写,t2读;
如果t1或t2有任何触发器,触发器内使用的表也将被锁定。假设t1有一个像这样定义的触发器:
CREATE TRIGGER t1_a_ins AFTER INSERT ON t1 FOR EACH ROW
开始
UPDATE t4 SET count = count + 1
WHERE id = NEW.ID AND EXISTS(SELECT a FROM t3);
插入t2值(1,2);
结束;
该结果LOCK TABLES
语句是t1和
t2被锁定,因为它们出现在语句,t3并且t4
被锁定,因为它们是触发内使用:
t1被锁定以便根据WRITE锁定请求进行写入
。
t2被锁定写入,即使请求是READ锁定的。发生这种情况是因为t2被插入触发器中,所以READ请求被转换为WRITE请求。
t3 被锁定读取,因为它只能从触发器中读取。
t4 被锁定写入,因为它可能在触发器内被更新。
您可以安全地使用KILL终止正在等待表锁的会话。请参见
第13.7.6.4节“KILL语法”。
LOCK TABLES并且
UNLOCK
TABLES不能在存储的程序中使用。
在表performance_schema的数据库不能被锁定LOCK
TABLES,除了
表。
setup_xxx
而下面的语句是禁止的
LOCK TABLES:声明生效CREATE TABLE,
CREATE TABLE ...
LIKE,CREATE VIEW,
DROP VIEW,和存储函数和过程和事件DDL语句。
对于某些操作,mysql必须访问数据库中的系统表
。例如,该HELP语句需要服务器端帮助表的内容,并且
CONVERT_TZ()可能需要读取时区表。服务器根据需要隐式锁定系统表以进行读取,以便您不需要明确锁定它们。这些表格按照刚刚描述的方式处理:
mysql.help_category mysql.help_keyword mysql.help_relation mysql.help_topic mysql.proc的 mysql.time_zone mysql.time_zone_leap_second mysql.time_zone_name mysql.time_zone_transition mysql.time_zone_transition_type
如果你想WRITE用一条LOCK
TABLES语句显式地在这些表上放置一个锁,那么该表必须是唯一锁定的表; 没有其他表可以用相同的语句锁定。
通常情况下,您不需要锁定表,因为所有单个
UPDATE语句都是原子的; 没有其他会话可以干扰任何其他当前正在执行的SQL语句。但是,有些情况下,锁定表可能会提供一个优点:
如果要在一组MyISAM表上运行很多操作
,锁定要使用的表会快得多。锁定
MyISAM表会加快插入,更新或删除操作,因为UNLOCK
TABLES在调用锁定表之前,MySQL不会刷新锁定表的键缓存
。通常,在每个SQL语句之后刷新密钥缓存。
锁定表的不利之处在于没有会话可以更新已READ锁定的表(包括持有锁的WRITE那个表),并且没有会话可以访问
除了持有锁之外的已锁定表。
如果您将表用于非事务性存储引擎,则必须使用LOCK
TABLES该表,以确保没有其他会话修改a SELECT和an
之间的表
UPDATE。此处显示的示例需要LOCK TABLES安全执行:
锁定表trans READ,客户WRITE; SELECT SUM(value)FROM trans WHERE customer_id =some_id; 更新客户 SET total_value =sum_from_previous_statementWHERE customer_id =some_id; 解锁表;
在没有的LOCK TABLES情况下,另一个会话可能会trans在执行SELECT和
UPDATE语句之间的表中
插入一个新行
。
您可以LOCK TABLES
通过使用相对更新()或函数来避免在许多情况下使用。
UPDATE
customer SET
value=value+new_valueLAST_INSERT_ID()
在某些情况下,您还可以通过使用用户级通知锁定功能
GET_LOCK()和
RELEASE_LOCK()。这些锁被保存在服务器的哈希表中,
pthread_mutex_lock()并
pthread_mutex_unlock()以高速实现。参见
第12.20节“其他功能”。
有关锁定策略的更多信息,请参见第8.11.1节“内部锁定方法”。
SET [GLOBAL | SESSION] TRANSACTION
transaction_characteristic[,transaction_characteristic] ...
transaction_characteristic:
隔离水平 level
| 读写
| 只读
level:
可重复阅读
| READ COMMITTED
| 阅读未读
| SERIALIZABLE
此声明指定
交易
特征。它采用由逗号分隔的一个或多个特征值的列表。这些特征设置事务隔离级别或访问模式。隔离级别用于InnoDB表上的操作。访问模式可以指定事务是以读/写还是只读模式运行。
另外,SET TRANSACTION可以包含一个可选GLOBAL或
SESSION关键字来表示声明的范围。
您可以为全球,当前会话或下一个事务设置交易特征:
使用GLOBAL关键字,该声明适用于所有后续会话的全局。现有会话不受影响。
使用SESSION关键字,该声明适用于当前会话中执行的所有后续事务。
没有任何SESSION或
GLOBAL关键字,该语句适用于当前会话中执行的下一个(未启动)事务。后续事务恢复为使用
SESSION隔离级别。
交易特征的全球变化需要
SUPER特权。任何会话都可以自由更改其会话特征(即使在交易中),或者其下一个交易的特征。
SET TRANSACTION没有
GLOBAL或SESSION不允许有一个活跃的交易:
MySQL的>START TRANSACTION;查询OK,0行受影响(0.02秒) MySQL的>SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;错误1568(25001):交易特征无法更改 而交易正在进行中
要设置在服务器启动全局默认隔离级别,使用
选项mysqld的在命令行或在选项文件。值此选项使用破折号,而不是空间,所以允许值是,
,
,或
。例如,要将默认隔离级别设置为
,请在选项文件的部分中使用以下行:
--transaction-isolation=levellevelREAD-UNCOMMITTEDREAD-COMMITTEDREPEATABLE-READSERIALIZABLEREPEATABLE READ[mysqld]
的[mysqld] 事务隔离= REPEATABLE-READ
通过使用transaction_isolation系统变量,可以在运行时检查或设置全局和会话事务隔离级别
:
SELECT @@ GLOBAL.transaction_isolation,@@ transaction_isolation; SET GLOBAL transaction_isolation ='REPEATABLE-READ'; SET SESSION transaction_isolation ='SERIALIZABLE';
在MySQL 5.7.20之前,使用
tx_isolation而不是
transaction_isolation。
同样,要在服务器启动时或运行时设置事务访问模式,请使用
--transaction-read-only选项或
transaction_read_only系统变量。默认情况下,这些是OFF(模式是读取/写入),但可以设置ON为仅读取的默认模式。
在MySQL 5.7.20之前,使用
tx_read_only而不是
transaction_read_only。
设置的全局或会话值
transaction_isolation或
transaction_read_only等效于设置隔离级别或访问模式
SET GLOBAL
TRANSACTION或
SET SESSION
TRANSACTION。
有关事务隔离级别的信息,请参见 第14.5.2.1节“事务隔离级别”。
事务访问模式可以用指定
SET TRANSACTION。默认情况下,事务以读/写模式进行,读写允许事务中使用的表。该模式可以使用访问模式明确指定READ
WRITE。
如果事务访问模式设置为READ
ONLY,则禁止更改表格。这可能使存储引擎在不允许写入时可以提高性能。
它不允许同时指定READ WRITE
,并READ ONLY在同一语句。
在只读模式下,仍然可以TEMPORARY使用DML语句更改使用关键字创建的表。正如永久表一样,不允许使用DDL语句进行更改。
该READ WRITE和READ ONLY
接入方式也可以使用一个独立的事务中指定START
TRANSACTION的语句。
支持XA事务可用于InnoDB存储引擎。MySQL XA实现基于X / Open CAE文档分布式事务处理:XA规范。本文档由The Open Group发布,可在
http://www.opengroup.org/public/pubs/catalog/c193.htm获取。当前XA实现的限制在
第C.6节“XA事务的限制”中进行了描述。
在客户端,没有特殊要求。到MySQL服务器的XA接口由以XA关键字开头的SQL语句组成。MySQL客户端程序必须能够发送SQL语句并理解XA语句接口的语义。它们不需要与最近的客户端库链接。旧的客户端库也可以工作。
在MySQL连接器中,MySQL Connector / J 5.0.0和更高版本通过为您处理XA SQL语句接口的类接口直接支持XA。
XA支持分布式事务,即允许多个独立的事务资源参与全局事务。事务性资源通常是RDBMS,但可能是其他类型的资源。
全局事务涉及多个本身是事务性的操作,但是所有操作都必须以组的形式成功完成,或者全部作为一个组来回滚。实质上,这将ACID属性“ 向上 ”扩展,以便多个ACID事务可以作为也具有ACID属性的全局操作的组件一起执行。(与非分布式交易一样,SERIALIZABLE如果您的应用程序对读取现象敏感,可能会优先使用,
可能
REPEATABLE READ不足以用于分布式交易。)
分布式事务的一些例子:
应用程序可以充当将消息传递服务与RDBMS相结合的集成工具。应用程序确保处理消息发送,检索和处理的事务也涉及事务数据库,这些事务都发生在全局事务中。您可以将其视为 “ 交易电子邮件”。”
应用程序执行涉及不同数据库服务器(如MySQL服务器和Oracle服务器(或多个MySQL服务器))的操作,其中涉及多个服务器的操作必须作为全局事务的一部分发生,而不是作为每个服务器本地的单独事务。
银行将账户信息保存在RDBMS中,并通过自动取款机(ATM)分配和接收资金。有必要确保自动柜员机的行为在账户中得到正确反映,但这仅靠RDBMS无法完成。全球交易管理器整合了ATM和数据库资源,以确保金融交易的整体一致性。
使用全局事务的应用程序涉及一个或多个资源管理器和事务管理器:
资源管理器(RM)提供对事务资源的访问。数据库服务器是一种资源管理器。必须能够提交或回滚由RM管理的交易。
交易管理器(TM)协调作为全局交易一部分的交易。它与处理每个交易的RM进行通信。全球交易中的单个交易是全球交易的 “ 分支 ”。全球交易及其分支机构由后面所述的命名机制来标识。
MySQL的MySQL实现使MySQL服务器充当资源管理器来处理全局事务中的XA事务。连接到MySQL服务器的客户端程序充当事务管理器。
要执行全局事务,有必要知道涉及哪些组件,并在每个组件可以提交或回滚时将它们带到某个点。根据每个组件报告的成功能力,它们必须全部提交或回滚为原子组。也就是说,所有组件都必须提交,否则所有组件都必须回滚。要管理全局事务,有必要考虑到任何组件或连接网络可能会失败。
执行全局事务的过程使用两阶段提交(2PC)。这发生在全局事务的分支执行的操作被执行之后。
在第一阶段,所有分支都准备好了。也就是说,TM被告知他们准备提交。通常情况下,这意味着每个管理分支的RM都记录分支在稳定存储中的操作。分支表明他们是否能够做到这一点,并将这些结果用于第二阶段。
在第二阶段,TM告诉RM是否提交或回滚。如果所有分支在准备好时表示他们能够提交,所有分支都被告知提交。如果任何分支在准备好时表示无法提交,则会告知所有分支回滚。
在某些情况下,全局事务可能使用单阶段提交(1PC)。例如,当一个事务管理器发现一个全局事务只包含一个事务资源(即一个分支)时,该资源可以被告知同时准备和提交。
要在MySQL中执行XA事务,请使用以下语句:
XA {START | BEGIN} xid[加入|恢复]
XA结束xid[暂停[迁移]]
XA PREPARE xid
XA COMMIT xid[单阶段]
XA ROLLBACK xid
XA RECOVER [转换XID]
因为XA
START,JOIN和
RESUME子句不受支持。
对于XA
END该SUSPEND [FOR MIGRATE]
条款不支持。
每个XA语句都以XA关键字开头,其中大多数都需要一个xid
值。An xid是XA事务标识符。它指示该语句适用于哪个事务。xid值由客户端提供,或者由MySQL服务器生成。一个
xid值有一到三个部分:
xid:gtrid[,bqual[,formatID]]
gtrid是一个全局事务标识符,bqual是一个分支限定符,formatID是一个用于标识gtrid和
bqual值使用的格式的数字
。如语法所示,bqual并且
formatID是可选的。
如果没有给出默认
bqual值''。formatID
如果没有给出,默认值是1。
gtrid并且
bqual必须是字符串文字,每个长度最多为64个字节(不是字符)。
gtrid并
bqual可以用几种方式指定。您可以使用带引号的字符串('ab'),十六进制字符串(X'6162',0x6162)或位值()。
b'nnnn'
formatID 是一个无符号整数。
该gtrid和
bqual值以字节为MySQL服务器的底层XA支持例程解释。但是,虽然包含XA语句的SQL语句正在被解析,但服务器使用某些特定的字符集。为了安全起见,请将gtrid其
bqual写成十六进制字符串。
xid值通常由事务管理器生成。一个TM生成的值必须与其他TM生成的值不同。给定的TM必须能够xid在XA
RECOVER语句返回的值列表中识别它自己的值
。
用于启动具有给定值的XA事务。每个XA事务都必须具有唯一
值,因此该值当前不能被另一个XA事务使用。使用和
值来评估唯一性。以下XA事务的所有XA语句必须使用与声明中给出的值相同的值
来指定。如果您使用任何这些语句,但指定的值与某些现有XA事务不符,则会发生错误。
XA START
xidxidxidgtridbqualxidXA
STARTxid
一个或多个XA事务可以是同一全局事务的一部分。给定全局事务中的所有XA事务都必须使用相同gtrid
的xid值。出于这个原因,gtrid值必须是全局唯一的,以便关于给定的XA事务属于哪个全局事务不存在歧义。对于全局事务中的每个XA事务bqual,xid值的
部分
必须不同。(bqual值不同的要求是当前MySQL XA实现的限制,它不是XA规范的一部分。)
该XA
RECOVER语句返回处于该PREPARED状态的MySQL服务器上的那些XA事务的信息
。(请参见
第13.3.7.2节“XA事务状态”。)输出包括服务器上每个此类XA事务的一行,而不管哪个客户端启动它。
XA
RECOVER输出行如下所示(对于例如
xid由部件的值
'abc','def'和
7):
MySQL的> XA RECOVER;
+ ---------- + -------------- -------------- + -------- + +
| formatID | gtrid_length | bqual_length | 数据|
+ ---------- + -------------- -------------- + -------- + +
| 7 | 3 | 3 | abcdef |
+ ---------- + -------------- -------------- + -------- + +
输出列具有以下含义:
formatID是formatID交易的
一部分
xid
gtrid_length是该gtrid部分的
字节长度xid
bqual_length是该bqual部分的
字节长度xid
data是
gtrid和的
bqual部分的连接
xid
XID值可能包含不可打印的字符。从MySQL 5.7.5开始,XA
RECOVER允许使用可选CONVERT
XID子句,以便客户端可以请求十六进制的XID值。
XA事务处理通过以下状态进行:
使用XA
START启动一个XA事务,并把它的
ACTIVE状态。
对于ACTIVEXA事务,发出构成事务的SQL语句,然后发出XA
END语句。
XA
END将交易置于该
IDLE状态。
对于IDLEXA事务,您可以发出XA
PREPARE声明或XA COMMIT ... ONE
PHASE声明:
XA
PREPARE将交易置于该
PREPARED状态。此时的
XA
RECOVER语句将xid在其输出中包含事务的值,因为
XA
RECOVER列出了处于该PREPARED状态的所有XA事务。
XA COMMIT ... ONE PHASE准备并提交交易。该
xid值不会XA
RECOVER因事务终止而被列出。
对于PREPAREDXA事务,您可以发出XA
COMMIT声明来提交和终止事务,或者
XA
ROLLBACK回滚并终止事务。
这是一个简单的XA事务,它将全局事务的一部分插入到表中:
MySQL的>XA START 'xatest';查询OK,0行受影响(0.00秒) MySQL的>INSERT INTO mytable (i) VALUES(10);查询OK,1行受影响(0.04秒) MySQL的>XA END 'xatest';查询OK,0行受影响(0.00秒) MySQL的>XA PREPARE 'xatest';查询OK,0行受影响(0.00秒) MySQL的>XA COMMIT 'xatest';查询OK,0行受影响(0.00秒)
在给定客户端连接的上下文中,XA事务和本地(非XA)事务是相互排斥的。例如,如果XA
START已发出以开始XA事务,则在XA事务已提交或回滚之前无法启动本地事务。相反,如果本地事务已经开始
START
TRANSACTION,那么在事务被提交或回滚之前,不能使用XA语句。
如果XA事务处于该ACTIVE状态,则不能发出导致隐式提交的任何语句。这将违反XA合同,因为您无法回滚XA交易。如果您尝试执行这样的语句,您将收到以下错误:
错误1399(XAE07):XAER_RMFAIL:命令无法执行 当全局事务处于ACTIVE状态时
第13.3.3节“导致隐式提交的语句” 列出了前面的注释适用的 语句。
可以使用本节中描述的语句通过SQL接口来控制复制。语句分为控制主服务器的组,控制从属服务器的组以及可应用于任何复制服务器的组。
本节讨论用于管理主复制服务器的语句。第13.4.2节“用于控制从属服务器的SQL语句”讨论了用于管理从属服务器的语句。
除了这里描述的陈述之外,以下
SHOW陈述与复制中的主服务器一起使用。有关这些语句的信息,请参见第13.7.5节“SHOW语法”。
PURGE {BINARY | MASTER}日志
{去' log_name'| BEFORE datetime_expr}
二进制日志是一组包含由MySQL服务器进行的数据修改信息的文件。该日志由一组二进制日志文件和一个索引文件组成(请参见 第5.4.4节“二进制日志”)。
该PURGE BINARY LOGS语句会在指定的日志文件名称或日期之前删除日志索引文件中列出的所有二进制日志文件。
BINARY并且MASTER是同义词。删除的日志文件也会从记录在索引文件中的列表中删除,以便给定的日志文件成为列表中的第一个。
如果服务器未--log-bin启用启用二进制日志记录的选项,则此语句不起作用。
例子:
PURGE BINARY LOGS TO'mysql-bin.010'; 'PURGE BINARY LOGS''2008-04-02 22:46:26';
该BEFORE变种的
datetime_expr参数值应该为一个DATETIME值(一个值'YYYY-MM-DD hh:mm:ss'格式)。
这个语句可以安全的在奴隶复制时运行。你不需要阻止他们。如果您有一个当前正在读取要删除的日志文件之一的活动奴隶,则此语句不会删除正在使用的日志文件或晚于该日志文件的任何日志文件,但会删除任何较早的日志文件。在这种情况下发出警告消息。但是,如果从站未连接,而您恰好清除了尚未读取的某个日志文件,则从站在重新连接后将无法复制。
要安全地清除二进制日志文件,请遵循以下过程:
在每台从服务器上,用于SHOW SLAVE
STATUS检查它正在读取哪个日志文件。
获取主服务器上的二进制日志文件列表SHOW BINARY LOGS。
确定所有从站中最早的日志文件。这是目标文件。如果所有的从站都是最新的,这是列表中的最后一个日志文件。
备份您即将删除的所有日志文件。(这一步是可选的,但始终是可取的。)
清除所有日志文件,但不包括目标文件。
您还可以将expire_logs_days系统变量设置为
在给定天数后自动过期二进制日志文件(请参见第5.1.5节“服务器系统变量”)。如果您正在使用复制,则应该设置变量不低于您的奴隶可能落后于主人的最大天数。
PURGE BINARY LOGS TOPURGE
BINARY LOGS BEFORE当.index通过其他方式(如在Linux上使用rm)从系统中删除
文件中列出的二进制日志文件时,这两个文件都会失败并出现错误。(错误#18199,错误#18453)要处理此类错误,请.index手动编辑该文件(这是一个简单的文本文件),以确保它仅列出实际存在的二进制日志文件,然后再次运行PURGE BINARY LOGS
失败的语句。
RESET MASTER
删除索引文件中列出的所有二进制日志文件,将二进制日志索引文件重置为空,并创建新的二进制日志文件。
请谨慎使用此语句,以确保不会丢失二进制日志文件数据。
RESET MASTER也清除gtid_purged系统变量的值以及
系统变量的全局值
gtid_executed(但不是其会话值); 也就是说,执行这个语句将每个这些值设置为一个空字符串('')。在MySQL 5.7.5及更高版本中,该语句也会清除mysql.gtid_executed
表(请参阅
mysql.gtid_executed表)。
其效果RESET MASTER
与PURGE BINARY
LOGS2个关键方面的效果不同:
RESET MASTER删除
索引文件中列出的所有二进制日志文件,只留下一个带有数字后缀的单个空二进制日志文件.000001,而编号不会被重置
PURGE BINARY LOGS。
RESET MASTER是
不是打算,而任何复制的奴隶正在运行使用。RESET MASTER在奴隶运行时使用的行为
未定义(因此不受支持),而PURGE BINARY
LOGS在复制从属运行时可以安全使用。
RESET MASTER 在您首次设置主设备和从设备时可以证明有用,以便您可以验证设置,如下所示:
启动主服务器和从服务器,并开始复制(请参见 第16.1.2节“设置基于二进制日志文件的位置复制”)。
在主服务器上执行一些测试查询。
检查查询是否复制到从站。
当复制运行正常,问题
STOP SLAVE后面
RESET SLAVE的奴隶,然后验证任何不必要的数据不再存在于奴隶。
问题RESET MASTER在主清理测试查询。
验证设置后,重新设置主站和从站,并确保没有由测试生成的不需要的数据或二进制日志文件保留在主站或从站上,您可以启动从站并开始复制。
SET sql_log_bin = {0 | 1}
该sql_log_bin变量控制是否记录到二进制日志完成。默认值是1(做日志记录)。要更改当前会话的日志记录,请更改此变量的会话值。会话用户必须有权SUPER
设置此变量。将此变量设置为0,以便会话在临时禁用二进制日志记录的同时更改您不想复制到从属服务器的主服务器。
全局sql_log_bin变量是只读的,不能修改。全局范围已被弃用,并将在未来的MySQL版本中被删除。
无法@@session.sql_log_bin在事务或子查询中进行设置
。
本节讨论用于管理从属复制服务器的语句。第13.4.1节“用于控制主服务器的SQL语句”讨论了用于管理主服务器的语句。
除了此处描述的语句,
SHOW SLAVE STATUS并且
SHOW RELAYLOG EVENTS还使用复制的奴隶。有关这些语句的信息,请参见第13.7.5.34节“SHOW SLAVE STATUS语法”和
第13.7.5.32节“SHOW RELAYLOG EVENTS语法”。
将主设备更改为option[,option] ... [channel_option]option: MASTER_BIND ='interface_name' | MASTER_HOST ='host_name' | MASTER_USER ='user_name' | MASTER_PASSWORD ='password' | MASTER_PORT =port_num| MASTER_CONNECT_RETRY =interval| MASTER_RETRY_COUNT =count| MASTER_DELAY =interval| MASTER_HEARTBEAT_PERIOD =interval| MASTER_LOG_FILE ='master_log_name' | MASTER_LOG_POS =master_log_pos| MASTER_AUTO_POSITION = {0 | 1} | RELAY_LOG_FILE ='relay_log_name' | RELAY_LOG_POS =relay_log_pos| MASTER_SSL = {0 | 1} | MASTER_SSL_CA ='ca_file_name' | MASTER_SSL_CAPATH ='ca_directory_name' | MASTER_SSL_CERT ='cert_file_name' | MASTER_SSL_CRL ='crl_file_name' | MASTER_SSL_CRLPATH ='crl_directory_name' | MASTER_SSL_KEY ='key_file_name' | MASTER_SSL_CIPHER ='cipher_list' | MASTER_SSL_VERIFY_SERVER_CERT = {0 | 1} | MASTER_TLS_VERSION ='protocol_list' | IGNORE_SERVER_IDS =(server_id_list)channel_option: 对于频道channelserver_id_list: [server_id[,server_id] ...]
CHANGE MASTER TO更改从属服务器用于连接到主服务器的参数,读取主二进制日志以及读取从属中继日志。它还更新主信息和中继日志信息存储库的内容(请参见
第16.2.4节“复制中继和状态日志”)。CHANGE
MASTER TO需要
SUPER特权。
在MySQL 5.7.4之前,必须STOP SLAVE在发出此语句之前停止从属复制线程,必要时使用它。在MySQL 5.7.4和更高版本中,CHANGE MASTER TO
根据从属SQL线程和从属I / O线程的状态,您可以在不执行此操作的情况下在正在运行的从属系统上发出语句。本节稍后会提供管理此类使用的规则。
当使用多线程从属(换句话说
slave_parallel_workers是大于0),则停止从可引起
“ 间隙 ”已经从中继日志执行,而不管从设备是否被有意或以其他方式停止交易的序列英寸 当存在这种差距时,发布CHANGE MASTER TO
失败。这种情况下的解决方案是
START SLAVE UNTIL
SQL_AFTER_MTS_GAPS确保间隙关闭。
可选子句使您能够命名该语句适用于哪个复制通道。提供子句将语句应用于
特定的复制通道,并用于添加新通道或修改现有通道。例如,要添加一个名为channel2的新通道:
FOR CHANNEL
channelFOR CHANNEL
channelCHANGE MASTER TO
CHANGE MASTER TO MASTER_HOST = host1,MASTER_PORT = 3002 FOR CHANNEL'channel2'
如果没有子句被命名并且不存在额外的通道,则该语句适用于默认通道。
使用多个复制通道时,如果CHANGE
MASTER TO语句不使用子句命名通道
,则会发生错误。有关更多信息,请参见第16.2.3节“复制通道”。
FOR CHANNEL
channel
未指定的选项保留其值,除非在下面的讨论中指出。因此,在大多数情况下,不需要指定不改变的选项。例如,如果连接到您的MySQL主机的密码已更改,请发出以下语句以告知从机新密码:
将MASTER_PASSWORD改为MASTER_PASSWORD ='new3cret';
MASTER_HOST,MASTER_USER,
MASTER_PASSWORD,和
MASTER_PORT到有关如何连接到其主从提供信息:
MASTER_HOST并且
MASTER_PORT是主控主机及其TCP / IP端口的主机名(或IP地址)。
复制不能使用Unix套接字文件。您必须能够使用TCP / IP连接到主MySQL服务器。
如果您指定MASTER_HOST或
MASTER_PORT选项,从站会假定主服务器与以前不同(即使选项值与当前值相同)。在这种情况下,主二进制日志文件名和位置的旧值为考虑不再适用,因此,如果不指定MASTER_LOG_FILE,并
MASTER_LOG_POS在声明中,
MASTER_LOG_FILE=''并
MASTER_LOG_POS=4以静默追加到它。
设置MASTER_HOST=''(即,明确其值设置为空字符串)是
不一样的没有设置
MASTER_HOST在所有。从MySQL 5.5开始,尝试设置MASTER_HOST为空字符串会失败并显示错误。以前,设置
MASTER_HOST为空字符串导致
START SLAVE随后失败。(错误#28796)
对换行符(或)字符检查
用于MASTER_HOST和其他
CHANGE MASTER TO选项的值; 在这些值中出现这些字符会导致语句失败
。(错误#11758581,错误#50801)
\n0x0AER_MASTER_INFO
MASTER_USER并且
MASTER_PASSWORD是用于连接到主服务器的帐户的用户名和密码。
MASTER_USER不能变空; 设置
MASTER_USER = ''或设置的值时离开它未设置MASTER_PASSWORD
的原因的错误(错误#13427949)。
CHANGE MASTER TO语句中
用于MySQL Replication从属帐户的密码
长度限制为32个字符; 在MySQL 5.7.5之前,如果密码更长,则语句成功,但是任何多余的字符都会被自动截断。在MySQL 5.7.5及更高版本中,尝试使用超过32个字符的密码会导致CHANGE MASTER TO失败。(错误#11752299,错误#43439)
运行CHANGE MASTER
TO语句的文本(包括MASTER_USER和的
值)
MASTER_PASSWORD可以在并发SHOW
PROCESSLIST语句的输出中看到。(START SLAVE声明的全文
也可见SHOW PROCESSLIST。)
这些
选项提供有关使用SSL进行连接的信息。它们对应
于第6.4.2节“加密连接的命令选项”和
第16.3.8节“设置复制以使用加密连接”中所述的选项。即使在没有SSL支持的情况下编译的从站也可以更改这些选项。它们被保存到主信息库中,但如果从属设备未启用SSL支持,则会被忽略。
MASTER_SSL_xxx--ssl-xxx
从MySQL 5.7.3开始,这MASTER_SSL=1是规范性的,而不是建议性的。给定时,与主设备的从属连接必须使用SSL或连接尝试失败。在5.7.3之前,允许SSL连接但不是必需的。这与--ssl命令行选项的客户端含义类似
; 请参见
第6.4.2节“加密连接的命令选项”。
该MASTER_TLS_VERSION选项指定主设备允许的从设备连接的加密协议。该值与tls_version系统变量的值类似
:包含一个或多个协议名称的逗号分隔列表。可以为这个选项命名的协议取决于用于编译MySQL的SSL库。有关详细信息,请参见
第6.4.6节“加密连接协议和密码”。
MASTER_CONNECT_RETRY指定连接重试之间等待的秒数。默认值是60。
MASTER_RETRY_COUNT限制
数目的重新连接尝试的和更新的值Master_Retry_Count中的输出列中SHOW SLAVE STATUS。默认值为24 * 3600 = 86400.
MASTER_RETRY_COUNT用于替换旧
--master-retry-count
服务器选项,现在是设置此限制的首选方法。鼓励您不要依赖
--master-retry-count新应用程序,并且在从早于MySQL 5.6的版本升级时更新所有依赖它的现有应用程序,以便它们可以使用CHANGE MASTER TO ...
MASTER_RETRY_COUNT。
MASTER_DELAY指定从站必须滞后的主站后面多少秒。从主站接收的事件至少要interval晚于主站执行的时间才会
执行。默认值为0.如果interval不是0到2 31 -1 范围内的非负整数,则会发生错误
。有关更多信息,请参见第16.3.10节“延迟复制”。
从MySQL 5.7开始,当从属SQL线程停止时,CHANGE MASTER TO使用该MASTER_DELAY选项的语句可以在正在运行的从属设备上执行。
MASTER_BIND 用于具有多个网络接口的复制从站,并确定选择哪个从站的网络接口连接到主站。
使用此选项配置的地址(如果有)可以Master_Bind在输出的列中
看到SHOW SLAVE STATUS。如果您使用的是从属状态日志表(服务器启动时
--master-info-repository=TABLE),则该值也可以被视为表的Master_bind
列mysql.slave_master_info。
NDB集群还支持将复制从站绑定到特定网络接口的功能。
MASTER_HEARTBEAT_PERIOD设置复制心跳之间的时间间隔(以秒为单位)。每当主站的二进制日志更新为事件时,下一次心跳的等待时间将重置。interval是一个十进制值,范围为0到4294967秒,分辨率以毫秒为单位; 最小的非零值是0.001。仅当二进制日志文件中没有未发送事件的时间超过1秒钟时,才会由主服务器发送心跳
interval。
在MySQL 5.7.4之前,不包括
MASTER_HEARTBEAT_PERIOD导致
CHANGE MASTER TO将心跳周期(Slave_heartbeat_period)重置为默认值,并将
Slave_received_heartbeats其重置为0.(错误#18185490)
如果您将主连接信息记录到表中,则
MASTER_HEARTBEAT_PERIOD可以将其视为表的Heartbeat列
的值mysql.slave_master_info。
设置interval为0会完全禁用心跳。默认值
interval等于slave_net_timeout除以2 的值
。
设置@@global.slave_net_timeout为小于当前心跳间隔的值会导致发出警告。RESET SLAVE对心跳间隔发出的效果
是将其重置为默认值。
MASTER_LOG_FILE并且
MASTER_LOG_POS是下一次线程启动时从I / O线程应该从主服务器开始读取的坐标。RELAY_LOG_FILE
并且RELAY_LOG_POS是下一次线程启动时从属SQL线程应该从中继日志读取的坐标。如果您指定
MASTER_LOG_FILE或者
MASTER_LOG_POS,您不能指定
RELAY_LOG_FILE或
RELAY_LOG_POS。如果您指定
MASTER_LOG_FILE或者
MASTER_LOG_POS,您也不能指定
MASTER_AUTO_POSITION = 1(在本节后面介绍)。如果没有的MASTER_LOG_FILE
或MASTER_LOG_POS指定,从使用的最后一个坐标从SQL线程前CHANGE MASTER
TO发出。这可以确保在复制过程中不会出现中断,即使从属SQL线程比从属I / O线程晚,只需要更改(例如)要使用的密码时也是如此。
从MySQL 5.7开始,当从属SQL线程停止时,可以在正在运行的从属服务器上执行CHANGE MASTER TO使用RELAY_LOG_FILE,
RELAY_LOG_POS或两个选项的语句。
如果MASTER_AUTO_POSITION = 1用于
CHANGE MASTER TO,从机尝试使用基于GTID的复制协议连接到主机。从MySQL 5.7开始,CHANGE
MASTER TO只有在从属SQL和从属I / O线程都停止的情况下才能使用此选项。
当使用GTID时,从设备会通知主设备它已经收到,执行了哪些事务或两者。为了计算这个集合,它从中读取全局值
gtid_executed和Retrieved_gtid_set列
的值SHOW SLAVE STATUS。Retrieved_gtid_set只有收到完整的交易时才会包含上次传输的交易的GTID
。从站计算以下集合:
UNION(@@ global.gtid_executed,Retrieved_gtid_set)
在MySQL 5.7.5之前,Retrieved_gtid_set 即使事务只是部分传输,最后一次传输的事务的GTID也包含在内
,并且从该集合中减去最后收到的GTID。(错误#17943188)因此,从站计算出以下集合:
UNION(@@ global.gtid_executed,Retrieved_gtid_set - last_received_GTID)
该组作为初始握手的一部分发送给主设备,主设备将所有已执行的不属于该设备的事务发回。如果这些事务中的任何一个已经从主服务器的二进制日志中清除,则主服务器将该错误发送
ER_MASTER_HAS_PURGED_REQUIRED_GTIDS
给从服务器,并且复制不会启动。
使用基于GTID的复制时,将使用由MASTER_LOG_FILE和MASTER_LOG_POS不使用的坐标,并
使用全局事务标识符。因此,将这些选项中的任何一个或两个选项一起使用
MASTER_AUTO_POSITION会导致错误。
您可以通过检查输出来查看启用自动定位的复制是否正在运行SHOW
SLAVE STATUS。(错误#15992220)
gtid_mode发行前也必须启用CHANGE MASTER TO ...
MASTER_AUTO_POSITION = 1。否则,该语句会失败并显示错误。
要在使用GTID之后恢复到较早的基于文件的复制协议,您可以发出一条新CHANGE MASTER
TO语句来指定
MASTER_AUTO_POSITION = 0以及至少一个MASTER_LOG_FILE或
MASTER_LOG_POS。
在MySQL 5.7.4之前,CHANGE MASTER TO
删除所有中继日志文件并启动一个新文件,除非您指定RELAY_LOG_FILE或
RELAY_LOG_POS。在这种情况下,中继日志文件将保留; 该relay_log_purge
全局变量被静默设置为0。在MySQL 5.7.4和以后,中继日志如果保存从SQL线程和I / O线程正在运行从属中的至少一个; 如果两个线程均已停止,则除非至少指定了一个RELAY_LOG_FILE或
RELAY_LOG_POS已指定,否则将删除所有中继日志文件
。
RELAY_LOG_FILE可以使用绝对路径或相对路径,并使用与之相同的基本名称
MASTER_LOG_FILE。(错误#12190)
IGNORE_SERVER_IDS采用逗号分隔的0个或更多服务器ID列表。来自相应服务器的事件被忽略,除了日志轮转和删除事件,这些事件仍然记录在中继日志中。
在循环复制中,始发服务器通常作为其自身事件的终结器,以便它们不会多次应用。因此,当圆圈中的一台服务器被移除时,此选项在循环复制中非常有用。假设您有4台服务器的循环复制设置,服务器ID为1,2,3和4,服务器3出现故障。当通过开始从服务器2到服务器4的复制来弥补差距时,您可以在服务器4上发出IGNORE_SERVER_IDS =
(3)的CHANGE MASTER
TO声明中包含,以告诉它使用服务器2作为其主服务器而不是服务器3.这样做会导致它忽略而不是传播任何源于不再使用的服务器的语句。
如果CHANGE MASTER TO没有任何IGNORE_SERVER_IDS
选项发布声明,则保留任何现有列表。要清除被忽略的服务器列表,有必要使用带有空列表的选项:
将主人更改为IGNORE_SERVER_IDS =();
在MySQL 5.7.5之前,
RESET SLAVE
ALL不会影响服务器ID列表。在MySQL 5.7.5及更高版本中,RESET SLAVE ALL清除
IGNORE_SERVER_IDS。(Bug#18816897)
如果IGNORE_SERVER_IDS包含服务器自己的ID并且服务器在--replicate-same-server-id启用该
选项的情况下启动,则会产生错误。
主信息库和输出
SHOW SLAVE STATUS提供当前被忽略的服务器列表。有关更多信息,请参见第16.2.4.2节“从站状态日志”和
第13.7.5.34节“SHOW SLAVE STATUS语法”。
调用CHANGE MASTER TO导致原先的值MASTER_HOST,
MASTER_PORT,
MASTER_LOG_FILE,并
MASTER_LOG_POS要写入错误日志,以及有关从执行前的状态等信息。
CHANGE MASTER TO导致正在进行的交易的隐式提交。请参见第13.3.3节“导致隐式提交的语句”。
在MySQL 5.7.4及更高版本中,在STOP SLAVE发布任何CHANGE MASTER TO语句(以及
START SLAVE之后)之前
执行的严格要求将
被删除。取决于slave是否停止,CHANGE MASTER TO取决于(在MySQL 5.7.4及更高版本中)从属SQL线程和从属I / O线程状态的行为; 现在这些线程中的哪一个被停止或正在运行,这决定了可以或不可以CHANGE MASTER TO在给定时间点与语句一起使用的选项
。下面列出了做出这一决定的规则:
如果SQL线程停止时,可以执行
CHANGE MASTER TO使用被允许的其他方式的任意组合
RELAY_LOG_FILE,
RELAY_LOG_POS和
MASTER_DELAY选择,即使从I / O线程运行。当I / O线程运行时,此语句不能使用其他选项。
如果I / O线程停止时,可以执行
CHANGE MASTER TO使用任何选项,此语句(任何允许的组合)
除外
RELAY_LOG_FILE,
RELAY_LOG_POS或者
MASTER_DELAY,SQL线程运行时也是如此。当I / O线程运行时,这三个选项可能不会使用。
在发布使用的CHANGE MASTER TO
语句之前,必须停止SQL线程和I / O线程MASTER_AUTO_POSITION =
1。
您可以使用检查从属SQL和I / O线程的当前状态SHOW SLAVE STATUS。
有关更多信息,请参见 第16.3.7节“在故障切换期间切换主服务器”。
如果您正在使用基于语句的复制和临时表,则CHANGE MASTER TO
语句后面的STOP SLAVE语句可能会在从属表中留下临时表。从MySQL 5.7开始,ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO只要发生这种情况,就会发出警告()。Slave_open_temp_tables
在执行这样的CHANGE MASTER TO语句之前,通过确保系统状态变量的值等于0,
可以避免出现这种情况
。
CHANGE MASTER TO在您拥有主设备的快照并记录了与快照时间相对应的主二进制日志坐标时,可用于设置从设备。将快照加载到从站以将其与主站同步后,可以在从站上运行
以指定从站应该开始读取主二进制日志的坐标。
CHANGE MASTER TO
MASTER_LOG_FILE='log_name',
MASTER_LOG_POS=log_pos
以下示例更改从站使用的主服务器,并建立从站开始读取的主站二进制日志坐标。当您想要设置从服务器来复制主服务器时,会使用它:
改变主人
MASTER_HOST = 'master2.example.com',
MASTER_USER = '复制',
MASTER_PASSWORD =”password ',
MASTER_PORT = 3306,
MASTER_LOG_FILE = 'master2-bin.001',
MASTER_LOG_POS = 4,
MASTER_CONNECT_RETRY = 10;
下一个示例显示了一个不太经常使用的操作。当从站有中继日志文件时,它会用于您希望它由于某种原因再次执行。为此,主设备不需要可达。您只需使用
CHANGE MASTER TO并启动SQL线程(START SLAVE SQL_THREAD):
改变主人 RELAY_LOG_FILE =“从属中继bin.006”, RELAY_LOG_POS = 4025;
您甚至可以在非重复设置中使用第二项操作,使用独立的非服务器服务器在崩溃后进行恢复。假设你的服务器崩溃了,并且你已经从备份中恢复它。您想要重播服务器自己的二进制日志文件(不是中继日志文件,而是常规的二进制日志文件),命名为(例如)myhost-bin.*。首先,在一些安全的地方制作这些二进制日志文件的备份副本,以防万一您没有完全按照以下步骤操作并意外让服务器清除二进制日志。使用
SET GLOBAL relay_log_purge=0额外的安全性。然后启动服务器而不使用
--log-bin选项,而是使用--replicate-same-server-id,
--relay-log=myhost-bin(使服务器相信这些常规的二进制日志文件是中继日志文件)和--skip-slave-start
选项。服务器启动后,发出以下语句:
改变主人 RELAY_LOG_FILE = 'MYHOST-bin.153', RELAY_LOG_POS = 410, MASTER_HOST = 'some_dummy_string'; START SLAVE SQL_THREAD;
服务器读取并执行自己的二进制日志文件,从而实现崩溃恢复。恢复完成后,运行
STOP SLAVE,关闭服务器,清除主信息和中继日志信息存储库,然后使用其原始选项重新启动服务器。
指定该MASTER_HOST选项(即使使用虚拟值)也需要使服务器认为它是从服务器。
下表显示了字符串值选项的最大允许长度。
| 选项 | 最大长度 |
|---|---|
MASTER_HOST |
60 |
MASTER_USER |
16 |
MASTER_PASSWORD |
32 |
MASTER_LOG_FILE |
255 |
RELAY_LOG_FILE |
255 |
MASTER_SSL_CA |
255 |
MASTER_SSL_CAPATH |
255 |
MASTER_SSL_CERT |
255 |
MASTER_SSL_CRL |
255 |
MASTER_SSL_CRLPATH |
255 |
MASTER_SSL_KEY |
255 |
MASTER_SSL_CIPHER |
511 |
更改复制过滤器filter[,filter] [,...]filter: REPLICATE_DO_DB =(db_list) | REPLICATE_IGNORE_DB =(db_list) | REPLICATE_DO_TABLE =(tbl_list) | REPLICATE_IGNORE_TABLE =(tbl_list) | REPLICATE_WILD_DO_TABLE =(wild_tbl_list) | REPLICATE_WILD_IGNORE_TABLE =(wild_tbl_list) | REPLICATE_REWRITE_DB =(db_pair_list)db_list:db_name[,db_name] [,...]tbl_list:db_name.table_name[,db_table_name] [,...]wild_tbl_list: 'db_pattern.table_pattern'[,'db_pattern.table_pattern'] [,...]db_pair_list: (db_pair)[,(db_pair)] [,...]db_pair:from_db,to_db
CHANGE REPLICATION FILTER在从属设备上设置一个或多个复制过滤规则,就像使用复制过滤选项(如或)
启动从属mysqld一样
。与服务器选项不同,此语句不需要重新启动服务器即可生效,只需要先停止使用从属SQL线程
(并在之后重新启动
)。需要
特权。
--replicate-do-db--replicate-wild-ignore-tableSTOP SLAVE
SQL_THREADSTART SLAVE
SQL_THREADCHANGE
REPLICATION FILTERSUPER
以下列表显示了这些CHANGE REPLICATION
FILTER选项及其与
--replicate-*服务器选项的关系:
REPLICATE_DO_DB:包含基于数据库名称的更新。相当于
--replicate-do-db。
REPLICATE_IGNORE_DB:根据数据库名称排除更新。相当于
--replicate-ignore-db。
REPLICATE_DO_TABLE:根据表名包含更新。相当于
--replicate-do-table。
REPLICATE_IGNORE_TABLE:根据表名排除更新。相当于
--replicate-ignore-table。
REPLICATE_WILD_DO_TABLE:包含基于通配符模式匹配表名称的更新。相当于
--replicate-wild-do-table。
REPLICATE_WILD_IGNORE_TABLE:根据通配符模式匹配表名排除更新。相当于
--replicate-wild-ignore-table。
REPLICATE_REWRITE_DB:在从站上将新名称替换为主站上的指定数据库后,对从站执行更新。相当于
--replicate-rewrite-db。
确切的效果REPLICATE_DO_DB和
REPLICATE_IGNORE_DB过滤器取决于基于语句的还是基于行的复制是有效的。有关更多信息,请参见第16.2.5节“服务器如何评估复制过滤规则”。
CHANGE REPLICATION FILTER通过用逗号分隔
规则,可以在单个语句中创建多个复制过滤规则
,如下所示:
更改复制过滤器
REPLICATE_DO_DB =(d1),REPLICATE_IGNORE_DB =(d2);
发出刚刚显示的语句相当于使用选项
启动从属mysqld。
--replicate-do-db=d1
--replicate-ignore-db=d2
如果多次指定了相同的过滤规则,则实际只使用
最后一个这样的规则。例如,这里显示的两条语句具有完全相同的效果,因为REPLICATE_DO_DB
第一条语句中的第一条规则会被忽略:
更改复制过滤器
REPLICATE_DO_DB =(db1,db2),REPLICATE_DO_DB =(db3,db4);
更改复制过滤器
REPLICATE_DO_DB =(db3,db4);
此行为与--replicate-*筛选器选项的行为不同,
多次指定相同选项会导致创建多个筛选器规则。
不包含任何特殊字符的表和数据库的名称不需要引用。与使用的数值
REPLICATION_WILD_TABLE和
REPLICATION_WILD_IGNORE_TABLE是字符串表达式,可能含有(特殊)通配符,所以必须加引号。这在以下示例语句中显示:
更改复制过滤器
REPLICATE_WILD_DO_TABLE =('db1.old%');
更改复制过滤器
REPLICATE_WILD_IGNORE_TABLE =('db1.new%','db2.new%');
用于REPLICATE_REWRITE_DB
表示数据库名称对的值; 每个这样的值必须用括号括起来。以下语句db1将主站上的数据库上发生的语句重写
db2为从站上的数据库
:
更改复制过滤器REPLICATE_REWRITE_DB =((db1,db2));
刚才显示的语句包含两组括号,一个括号包含数据库名称对,另一个括号包含整个列表。这是perhap更容易地看到在下面的例子中,这创建了两个
rewrite-db规则,一个重写数据库
dbA来dbB,和一个重写数据库dbC到
dbD:
更改复制过滤器 REPLICATE_REWRITE_DB =((dbA,dbB),(dbC,dbD));
此声明保留任何现有的复制过滤规则不变; 要取消设置给定类型的所有过滤器,请将过滤器的值设置为明确为空的列表,如以下示例所示,该示例将删除所有现有
REPLICATE_DO_DB和
REPLICATE_IGNORE_DB规则:
更改复制过滤器
REPLICATE_DO_DB =(),REPLICATE_IGNORE_DB =();
以这种方式将过滤器设置为空将删除所有现有规则,不会创建任何新规则,也不会使用--replicate-*
命令行或配置文件中的选项还原在mysqld启动时设置的任何规则。
值与使用REPLICATE_WILD_DO_TABLE
,并REPLICATE_WILD_IGNORE_TABLE必须在格式
。在使用MySQL 5.7.5之前,虽然在这些选项中使用不合格的值可能会导致错误的结果,但并未严格执行此操作(错误#18095449)。
db_name.tbl_name
有关更多信息,请参见第16.2.5节“服务器如何评估复制过滤规则”。
SELECT MASTER_POS_WAIT('master_log_file',master_log_pos[,timeout] [,channel])
这实际上是一个功能,而不是一个声明。它用于确保从站读取和执行事件直至主站二进制日志中的给定位置。完整描述请参见 第12.20节“其他函数”。
RESET SLAVE [ALL] [channel_option]channel_option: 对于频道channel
RESET SLAVE使奴隶忘记了在主人的二进制日志中的复制位置。此语句旨在用于干净启动:清除主信息和中继日志信息存储库,删除所有中继日志文件,并启动新的中继日志文件。它也会重置为0,指定使用MASTER_DELAY选项指定的复制延迟
CHANGE MASTER
TO。RESET SLAVE不会更改gtid_executed或
的值gtid_purged。要使用
RESET SLAVE,必须停止从属复制线程,所以STOP SLAVE在发出之前
正在运行的从属器使用
RESET SLAVE。
所有中继日志文件都将被删除,即使它们尚未完全由从属SQL线程执行。(如果您已发出STOP SLAVE语句或从机高负载,则这是复制从机中可能存在的情况。)
可选子句使您能够命名该语句适用于哪个复制通道。提供子句将语句应用于
特定的复制通道。将一个子句与该
选项组合将删除指定的通道。如果没有通道被命名并且不存在额外的通道,则该语句适用于默认通道。在存在多个复制通道时发出没有子句的
语句将删除
所有复制通道并仅重新创建默认通道。有关
更多信息,请参见第16.2.3节“复制通道”。
FOR CHANNEL
channelFOR CHANNEL
channelRESET SLAVEFOR CHANNEL
channelALLRESET SLAVE
ALLFOR CHANNEL
channel
RESET SLAVE不会更改任何复制连接参数,例如保留在内存中的主控主机,主端口,主用户或主密码。这意味着START
SLAVE可以在不需要
CHANGE MASTER TO声明的情况下发布RESET SLAVE。
连接参数被重置RESET SLAVE
ALL。(RESET SLAVE接着重启slave mysqld也是这样。)
RESET SLAVE导致正在进行的交易的隐式提交。请参见第13.3.3节“导致隐式提交的语句”。
如果从属SQL线程在停止并RESET SLAVE发布时正在
复制临时表的过程中,则会在从属设备上删除这些已复制的临时表。
在MySQL 5.7.5之前,RESET SLAVE也有重新设置心跳周期(Slave_heartbeat_period)和
SSL_VERIFY_SERVER_CERT。这个问题已在MySQL 5.7.5及更高版本中修复。(Bug#18777899,错误#18778485)
在MySQL 5.7.5之前,RESET SLAVE ALL没有清楚IGNORE_SERVER_IDS设置的列表
CHANGE MASTER TO。在MySQL 5.7.5及更高版本中,语句清除了列表。(Bug#18816897)
在NDB群集复制从节点SQL节点上使用时,
RESET SLAVE清除该
mysql.ndb_apply_status表。在使用这个ndb_apply_status使用
NDB存储引擎的语句时,应该记住这一点,
并且被附属于从群集的所有SQL节点共享。
您可以通过
在执行之前执行来覆盖此行为
,这会
在这种情况下使从服务器清除表。
SET
GLOBAL
@@ndb_clear_apply_status=OFFRESET SLAVEndb_apply_status
SET GLOBAL sql_slave_skip_counter = N
这条语句跳过N
主设备的下一个事件。这对从语句引起的复制停止恢复很有用。
该语句仅在从属线程未运行时才有效。否则,它会产生一个错误。
使用此语句时,了解二进制日志实际上组织为一组称为事件组的序列是很重要的。每个事件组由一系列事件组成。
对于事务表,事件组对应于一个事务。
对于非事务性表,事件组对应于单个SQL语句。
单个事务可以包含对事务性和非事务性表的更改。
当您使用SET GLOBAL
sql_slave_skip_counter跳过事件并且结果位于组中间时,从站继续跳过事件直到它到达组的结尾。然后执行从下一个事件组开始。
START SLAVE [thread_types] [until_option] [connection_options] [channel_option]thread_types: [thread_type[,thread_type] ...]thread_type: IO_THREAD | SQL_THREADuntil_option: 直到{{SQL_BEFORE_GTIDS | SQL_AFTER_GTIDS} =gtid_set| MASTER_LOG_FILE ='log_name',MASTER_LOG_POS =log_pos| RELAY_LOG_FILE ='log_name',RELAY_LOG_POS =log_pos| SQL_AFTER_MTS_GAPS}connection_options: [USER ='user_name'] [PASSWORD ='user_pass'] [DEFAULT_AUTH ='plugin_name'] [PLUGIN_DIR ='plugin_dir']channel_option: 对于频道channelgtid_set:uuid_set[,uuid_set] ... | “”uuid_set:uuid:interval[:interval] ...uuid:hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhhh: [0-9,AF]interval:n[ -n] (n> = 1)
START SLAVE没有
thread_type选项启动两个从线程。I / O线程从主服务器读取事件并将它们存储在中继日志中。SQL线程从中继日志中读取事件并执行它们。
START SLAVE需要
SUPER特权。
如果START SLAVE成功启动从属线程,则返回时不会出现任何错误。但是,即使在这种情况下,也可能是从线程启动,然后停止(例如,因为它们无法连接到主服务器或读取其二进制日志或其他问题)。START SLAVE并没有警告你这件事。您必须检查从站的错误日志中是否有从属线程生成的错误消息,或者检查它们是否满意地运行SHOW
SLAVE STATUS。
在MySQL 5.7中,START SLAVE会导致正在进行的事务的隐式提交。请参见
第13.3.3节“导致隐式提交的语句”。
gtid_next必须设置为
AUTOMATIC在发布此声明之前。
可选子句使您能够命名该语句适用于哪个复制通道。提供子句将语句应用于
特定的复制通道。如果没有子句被命名并且不存在额外的通道,则该语句适用于默认通道。如果
语句在使用多个通道时没有定义通道,则此语句会为所有通道启动指定的线程。该声明不适用于频道。有关更多信息,请参见第16.2.3节“复制通道”。
FOR CHANNEL
channelFOR CHANNEL
channelSTART SLAVESTART SLAVEgroup_replication_recovery
MySQL支持可插拔的用户密码认证
START SLAVE与USER,
PASSWORD,DEFAULT_AUTH和
PLUGIN_DIR选项,如下面的列表中所述:
USER: 用户名。不能设置为空或空字符串,如果PASSWORD使用则不设置
。
PASSWORD:密码。
DEFAULT_AUTH:插件的名称; 默认是MySQL本地认证。
PLUGIN_DIR:插件的位置。
你不能使用SQL_THREAD指定的任何选项时USER,
PASSWORD,DEFAULT_AUTH,或者
PLUGIN_DIR,除非
IO_THREAD还提供了选项。
有关更多信息,请参见第6.3.9节“可插入认证”。
如果对任何这些选项使用不安全连接,服务器将发出警告以纯文本发送密码而不使用SSL / TLS是非常不安全的。
START SLAVE ... UNTIL支持使用全局事务标识符(GTID)的两个附加选项(请参见第 16.1.3
节“使用全局事务标识符进行复制”)。其中的每个都将一组一个或多个全局事务标识符
gtid_set作为参数(有关更多信息,请参阅
GTID集合)。
如果thread_type指定了no ,
START SLAVE UNTIL SQL_BEFORE_GTIDS则会导致从属SQL线程处理事务,直到它到达其中列出GTID 的第一个事务gtid_set。START SLAVE
UNTIL SQL_AFTER_GTIDS使从属线程处理所有事务,直到两个线程处理last完
事务为止
gtid_set。换言之,START SLAVE UNTIL
SQL_BEFORE_GTIDS使得从属SQL线程处理在到达第一个GTID之前发生的所有事务
gtid_set,并且
START SLAVE UNTIL SQL_AFTER_GTIDS使得从属线程处理所有事务,包括那些在其中找到GTID的事务gtid_set,直到每个人遇到一个其GTID不属于该集合的交易。SQL_BEFORE_GTIDS并且
SQL_AFTER_GTIDS各自支持
SQL_THREAD和IO_THREAD
选项,尽管IO_THREAD与它们一起使用目前没有效果。
例如,START SLAVE SQL_THREAD UNTIL
SQL_BEFORE_GTIDS =
3E11FA47-71CA-11E1-9E33-C80AA9429562:11-56使从SQL线程以处理来自其主始发的所有事务server_uuid是
3E11FA47-71CA-11E1-9E33-C80AA9429562,直到它遇到具有序列号11中的交易; 然后停止而不处理此事务。换句话说,直至并包括序列号为10的交易的所有交易都被处理。执行START SLAVE
SQL_THREAD UNTIL SQL_AFTER_GTIDS =
3E11FA47-71CA-11E1-9E33-C80AA9429562:11-56另一方面,将导致从属SQL线程获得刚刚从主服务器提到的所有事务,包括具有序列号11到56的所有事务,然后在不处理任何额外事务的情况下停止; 也就是说,序列号为56的事务将是从属SQL线程获取的最后一个事务。
在MySQL 5.7.3之前,SQL_AFTER_GTIDS一旦指定的事务完成,并没有停止从服务器,但一直等到收到另一个GTID事件(错误#14767986)。
在使用多线程从站时,在以下情况下,从中继日志执行的事务序列中可能存在间隔:
杀死协调器线程
在工作线程中发生错误之后
mysqld意外关闭
使用该START SLAVE
UNTIL SQL_AFTER_MTS_GAPS语句可以使多线程从属工作者线程只运行,直到在中继日志中找不到更多间隙,然后停止。该声明可以采取SQL_THREAD选项,但声明的效果保持不变。它对从I / O线程没有影响(并且不能与IO_THREAD选项一起使用
)。
发出START SLAVE从中继日志执行的事务的序列中的多线程从具有间隙生成警告。在这种情况下,解决方案是使用
START SLAVE UNTIL
SQL_AFTER_MTS_GAPS,然后发布
RESET SLAVE以删除任何剩余的中继日志。有关
更多信息,请参见
第16.4.1.33节“复制和事务不一致性”。
要将发生故障的多线程从设备更改为单线程模式,可以按所示顺序发出以下一系列语句:
从SLAVE开始直到SQL_AFTER_MTS_GAPS; SET @@ GLOBAL.slave_parallel_workers = 0; START SLAVE SQL_THREAD;
可以在输出中查看正在运行的START SLAVE ...语句的全部文本
,包括任何
USER或PASSWORD使用的值SHOW
PROCESSLIST。运行CHANGE MASTER TO
语句的文本也是如此,包括它用于MASTER_USER或的
任何值
MASTER_PASSWORD。
START SLAVE在I / O线程和SQL线程都启动后向用户发送确认。但是,I / O线程可能尚未连接。因为这个原因,显示
了一个成功的
START SLAVE原因
,但这并不能保证(因为
只有在I / O线程正在运行和连接时)。有关更多信息,请参见第13.7.5.34节“SHOW SLAVE STATUS语法”和
第16.1.7.1节“检查复制状态”。
SHOW SLAVE STATUSSlave_SQL_Running=YesSlave_IO_Running=YesSlave_IO_Running=Yes
您可以添加IO_THREAD和
SQL_THREAD选择语句以命名启动哪个线程。在SQL_THREAD
指定的任选项时不允许
USER,PASSWORD,
DEFAULT_AUTH,或
PLUGIN_DIR,除非
IO_THREAD也被提供选项。
可以添加
一个UNTIL子句(until_option在前面的语法中)来指定从设备应该启动并运行,直到SQL线程到达主二进制日志中的给定点,由MASTER_LOG_POS
MASTER_LOG_FILE选项指定或从属中继中的给定点日志,用RELAY_LOG_POS和
RELAY_LOG_FILE选项表示。当SQL线程到达指定的点时,它停止。如果SQL_THREAD在语句中指定了该
选项,则它仅启动SQL线程。否则,它会启动两个从线程。如果SQL线程正在运行,则该
UNTIL子句将被忽略并发出警告。您不能UNTIL在IO_THREAD选项中使用子句。
也可以START SLAVE UNTIL使用其中一个选项指定相对于给定GTID或一组GTID的停止点,SQL_BEFORE_GTIDS或者
SQL_AFTER_GTIDS如本节前面所述。当使用其中的一个选项,您可以指定
SQL_THREAD,IO_THREAD,这两个,或者两者都不是的。如果仅指定
SQL_THREAD,则只有从属SQL线程受到该语句的影响; 如果仅IO_THREAD
使用,则只有从I / O受到影响。如果两个
SQL_THREAD和IO_THREAD
使用,或者如果使用都没有,那么无论是SQL和I / O线程由语句影响。
该UNTIL子句不支持多线程从属,除非还在使用
SQL_AFTER_MTS_GAPS。
对于一个UNTIL条款,您必须指定以下任何一项:
这两种日志文件名,并在文件中的位置
无论是
SQL_BEFORE_GTIDS或者
SQL_AFTER_GTIDS
SQL_AFTER_MTS_GAPS
不要混合使用主站和中继日志选项。不要将日志文件选项与GTID选项混合使用。
任何UNTIL条件都会被后续STOP SLAVE语句,START SLAVE包含无UNTIL子句的
语句或服务器重新启动重置
。
指定日志文件和位置时,即使只有SQL线程受此语句影响,也可以使用该
IO_THREAD选项START SLAVE
... UNTIL。IO_THREAD在这种情况下,该选项将被忽略。使用其中一个GTID选项(SQL_BEFORE_GTIDS和
SQL_AFTER_GTIDS)时,上述限制不适用; 在GTID选项支持SQL_THREAD和
IO_THREAD,在本节前面所解释的。
该UNTIL子句可用于调试复制,或导致复制继续进行,直到您希望避免从复制事件为止。例如,如果DROP TABLE在主UNTIL站上执行了一个不明确的语句,则
可以使用它来告诉从站执行到该点,但没有进一步执行。要查找事件是什么,请将mysqlbinlog与主二进制日志或从属中继日志一起使用,或使用
SHOW BINLOG EVENTS语句。
如果您正在使用UNTIL从属进程在部分中复制查询,建议您使用
--skip-slave-start选项启动从属服务器,以防止从属服务器启动时SQL线程运行。在选项文件中而不是在命令行中使用此选项可能是最好的选择,这样意外的服务器重新启动不会导致它被遗忘。
该SHOW SLAVE STATUS语句包括显示UNTIL条件当前值的输出字段
。
在MySQL 5.7.5之前,该语句的失败导致从心跳周期被重置。这个问题已在MySQL 5.7.5及更高版本中修复。(错误#18791604)
在非常旧的MySQL版本中(4.0.5之前),这个语句被调用SLAVE START。该语法现在产生一个错误。
STOP SLAVE [thread_types]thread_types: [thread_type[,thread_type] ...]thread_type:IO_THREAD | SQL_THREADchannel_option: 对于频道channel
停止从线程。STOP
SLAVE需要
SUPER特权。推荐的最佳做法是STOP SLAVE在停止从服务器之前在从服务器上执行(有关更多信息,请参见
第5.1.13节“服务器关机过程”)。
使用基于行的记录格式时:如果要复制使用非事务存储引擎的任何表(请参阅本部分后面的注释),则应在关闭从属服务器之前执行STOP SLAVE或
STOP SLAVE SQL_THREAD在从属服务器上
执行。
就像START SLAVE,这个语句可以IO_THREAD和和
SQL_THREAD选项一起使用来命名要停止的线程或线程。
STOP SLAVE导致正在进行的交易的隐式提交。请参见第13.3.3节“导致隐式提交的语句”。
从MySQL 5.7开始,在发布此语句之前gtid_next必须设置为AUTOMATIC(Bug#16062608)。
从MySQL 5.7开始,您可以STOP
SLAVE通过设置rpl_stop_slave_timeout
系统变量来控制超时之前等待的时间
。这可以用来避免使用STOP SLAVE与从属设备不同的客户端连接的其他从属SQL语句之间的死锁
。当达到超时值时,发出客户端返回错误消息并停止等待,但STOP SLAVE
指令保持有效。一旦从属线程不再忙,STOP SLAVE语句就会执行并且从属程序停止。(Bug#16856735)
CHANGE MASTER TO根据从属SQL和I / O线程的状态,从属运行时允许
一些语句。但是,在这种情况下STOP
SLAVE执行之前的使用CHANGE MASTER
TO仍然受支持。有关更多信息,请参见
第13.4.2.1节“更改MASTER TO语法”和
第16.3.7节“在故障切换期间切换MASTER”。
可选子句使您能够命名该语句适用于哪个复制通道。提供子句将语句应用于
特定的复制通道。如果没有通道被命名并且不存在额外的通道,则该语句适用于默认通道。如果语句在使用多个通道时未命名通道,则此语句停止所有通道的指定线程。该声明不能与
频道一起使用。有关更多信息,请参见第16.2.3节“复制通道”。
FOR CHANNEL
channelFOR CHANNEL
channelSTOP SLAVESTOP SLAVEgroup_replication_recovery
使用基于语句的复制时:在打开临时表时更改主控可能不安全。这是为什么不建议临时表的基于语句的复制的原因之一。你可以通过检查slave的值来发现slave上是否有临时表
Slave_open_temp_tables。当使用基于语句的复制时,此值在执行前应为0CHANGE MASTER TO。如果从站上有任何临时表打开,发出aCHANGE
MASTER TO后发出一个语句STOP
SLAVE会引起
ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO
警告。
当使用多线程从站(slave_parallel_workers非零值)时,从中继日志执行的事务序列中的任何间隙都将作为停止工作线程的一部分而关闭。如果从被意外停止(例如,由于在辅助线程错误,或者另一个线程发布KILL),而
STOP SLAVE语句执行,执行的事务从中继日志的顺序可能会变得不一致。有关更多信息,请参见
第16.4.1.33节“复制和事务不一致性”。
如果当前复制事件组修改了一个或多个非事务表,则除非您
为从属SQL线程发出KILL QUERY或
KILL CONNECTION语句,否则STOP SLAVE将等待最多60秒以完成事件组
。如果事件组在超时后保持不完整,则会记录一条错误消息。
本节提供有关用于控制运行MySQL组复制插件的服务器的语句的信息。有关更多信息,请参见 第17章,组复制。
START GROUP_REPLICATION
在此服务器实例上启动组复制。该声明需要SUPER特权。如果
super_read_only=ON和成员应该作为主要连接,
super_read_only则OFF一旦成功启动组复制就设置为
成员。
停止GROUP_REPLICATION
停止组复制。该声明需要
SUPER特权。只要您发出STOP GROUP_REPLICATION成员设置为
super_read_only=ON,它确保在组复制停止时不能写入成员。
请谨慎使用此语句,因为它将该服务器实例从组中删除,这意味着它不再受组复制一致性保证机制的保护。为了完全安全,请确保在发布此语句之前,您的应用程序不能再连接到实例,以避免任何陈旧读取的机会。
MySQL 5.7提供了对服务器端预处理语句的支持。此支持利用高效的客户端/服务器二进制协议。使用准备好的语句和占位符来获取参数值具有以下好处:
每次执行时解析语句的开销都较小。通常情况下,数据库应用程序处理大量几乎相同的语句,只改变子句中的文字或变量值,例如WHERE查询和删除,SET更新和
VALUES插入。
防止SQL注入攻击。参数值可以包含未转义的SQL引号和分隔符字符。
您可以通过客户端编程接口使用服务器端预处理语句,包括MySQL C API客户端库或用于C程序的MySQL Connector / C,
用于Java程序的MySQL Connector / J和用于使用.NET技术的程序的MySQL Connector / Net。例如,C API提供了一组函数调用,这些函数调用组成其预先准备好的语句API。参见
第27.8.8节“C API准备语句”。其他语言接口可以通过链接到C客户端库中提供对使用二进制协议的预准备语句的支持,其中一个例子是PHP 5.0和更高版本中提供的
mysqli
扩展。
预备语句的备选SQL接口可用。这个接口不如通过预先准备好的语句API使用二进制协议那样高效,但不需要编程,因为它可直接在SQL级别使用:
当没有可用的编程接口时,您可以使用它。
您可以从任何可以将SQL语句发送到要执行的服务器的程序中使用它,例如mysql 客户端程序。
即使客户端使用旧版本的客户端库,只要连接到运行MySQL 4.1或更高版本的服务器即可使用它。
准备好的语句的SQL语法旨在用于以下情况:
在编写代码之前测试准备好的语句在应用程序中的工作方式
当您无法访问支持它们的编程API时使用预准备语句。
使用预准备语句交互式解决应用程序问题。
创建一个测试用例,用准备好的语句重现问题,以便您可以提交错误报告。
预准备语句的SQL语法基于三个SQL语句:
PREPARE准备执行语句(请参见第13.5.1节“PREPARE语法”)。
EXECUTE执行预准备语句(请参见第13.5.2节“EXECUTE语法”)。
DEALLOCATE PREPARE发布准备好的语句(请参见第13.5.3节“DEALLOCATE PREPARE语法”)。
下面的例子展示了准备计算三角形斜边的两种等价方法,给出了双方的长度。
第一个例子展示了如何通过使用字符串文字来提供语句的文本来创建一个准备好的语句:
mysql>PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';mysql>SET @a = 3;mysql>SET @b = 4;mysql>EXECUTE stmt1 USING @a, @b;+ ------------ + | 斜边| + ------------ + | 5 | + ------------ + MySQL的>DEALLOCATE PREPARE stmt1;
第二个例子是类似的,但将语句的文本作为用户变量提供:
mysql>SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';mysql>PREPARE stmt2 FROM @s;mysql>SET @a = 6;mysql>SET @b = 8;mysql>EXECUTE stmt2 USING @a, @b;+ ------------ + | 斜边| + ------------ + | 10 | + ------------ + MySQL的>DEALLOCATE PREPARE stmt2;
下面是一个附加示例,演示如何选择要在运行时执行查询的表,方法是将表的名称存储为用户变量:
mysql>USE test;mysql>CREATE TABLE t1 (a INT NOT NULL);mysql>INSERT INTO t1 VALUES (4), (8), (11), (32), (80);mysql>SET @table = 't1';mysql>SET @s = CONCAT('SELECT * FROM ', @table);mysql>PREPARE stmt3 FROM @s;mysql>EXECUTE stmt3;+ ---- + | a | + ---- + | 4 | | 8 | | 11 | | 32 | | 80 | + ---- + MySQL的>DEALLOCATE PREPARE stmt3;
准备好的声明特定于创建它的会话。如果您在不取消分配先前准备的语句的情况下终止会话,服务器会自动释放它。
准备好的声明也是全球会议。如果您在已存储的例程中创建预准备语句,则在存储的例程结束时不会释放它。
为了防止同时创建的准备语句过多,请设置
max_prepared_stmt_count系统变量。要防止使用预准备语句,请将该值设置为0。
以下SQL语句可用作预准备语句:
改变表
改变用户
分析表
CACHE INDEX
呼叫
改变主人
CHECKSUM {TABLE | TABLES}
承诺
{CREATE | DROP}索引
{CREATE | RENAME | DROP}数据库
{CREATE | DROP}表
{CREATE | RENAME | DROP} USER
{CREATE | DROP} VIEW
删除
做
FLUSH {TABLE | 表格| 带有读锁的表| | HOSTS | 特权
| LOGS | STATUS | MASTER | SLAVE | DES_KEY_FILE | USER_RESOURCES}
GRANT
插
安装插件
杀
将索引加载到缓存中
优化表
重命名表
修理桌
更换
RESET {MASTER | SLAVE | QUERY CACHE}
撤消
选择
组
显示{警告| 错误}
显示BINLOG事件
SHOW CREATE {PROCEDURE | 功能| 事件| TABLE | 视图}
SHOW {MASTER | BINARY}日志
SHOW {MASTER | 从属}状态
从属{开始| 停}
TRUNCATE TABLE
卸载插件
UPDATE
从MySQL 5.7.2开始,为了遵守声明诊断语句不可预备的SQL标准,MySQL不支持以下为预处理语句:
SHOW WARNINGS, SHOW COUNT(*)
WARNINGS
SHOW ERRORS, SHOW COUNT(*)
ERRORS
包含对任何参考语句
warning_count或
error_count系统变量。
其他语句在MySQL 5.7中不受支持。
一般来说,SQL准备语句中不允许的语句在存储的程序中也是不允许的。第C.1节“对存储程序的限制”中有例外 。
对准备好的语句引用的表或视图的元数据更改会被检测到,并在下次执行时导致语句自动重新编译。有关更多信息,请参见 第8.10.4节“准备好的语句和存储的程序的缓存”。
LIMIT使用预处理语句时,
可以使用占位符作为子句的参数
。请参见
第13.2.9节“SELECT语法”。
在准备CALL与使用的语句
PREPARE,并
EXECUTE为占位符的支持
OUT和INOUT参数可与MySQL 5.7开始。有关早期版本的示例和解决方法,请参见
第13.2.1节“CALL语法”。IN
无论版本如何,占位符均可用于参数。
预处理语句的SQL语法不能以嵌套方式使用。也就是说,传递给一个说法
PREPARE本身不能成为一个
PREPARE,
EXECUTE或
DEALLOCATE PREPARE声明。
预处理语句的SQL语法与使用预处理语句API调用截然不同。例如,您不能使用
mysql_stmt_prepare()C API函数来准备PREPARE,
EXECUTE或
DEALLOCATE PREPARE声明。
预编译语句的SQL语法可以在存储过程中使用,但不能在存储函数或触发器中使用。然而,光标不能用于被制备并用执行的动态语句PREPARE和
EXECUTE。游标创建时检查游标语句,因此语句不能为动态语句。
预准备语句的SQL语法不支持多语句(也就是说,单个字符串中的多个语句由;字符分隔
)。
Prepared语句在第8.10.3.1节“查询缓存如何操作”中描述的条件下使用查询缓存。
要编写使用CALL
SQL语句执行包含预处理语句的存储过程的C程序,CLIENT_MULTI_RESULTS必须启用该标志。这是因为CALL
除了过程中执行的语句可能返回的任何结果集外,每个结果都会返回一个结果来指示调用状态。
CLIENT_MULTI_RESULTS可以在你打电话时启用
mysql_real_connect(),或者明确地通过传递CLIENT_MULTI_RESULTS
标志本身,或者通过传递CLIENT_MULTI_STATEMENTS(也启用CLIENT_MULTI_RESULTS)隐式地
启用
。有关更多信息,请参见第13.2.1节“CALL语法”。
准备stmt_name从preparable_stmt
该PREPARE语句准备一个SQL语句并为其指定一个名称,stmt_name稍后通过该名称
来引用该语句。准备好的语句随执行并随之
EXECUTE发布
DEALLOCATE PREPARE。有关示例,请参见第13.5节“准备好的SQL语句语法”。
语句名称不区分大小写。
preparable_stmt是一个字符串文字或包含SQL语句文本的用户变量。文本必须代表一个陈述,而不是多个陈述。在该语句中,?
可以使用字符作为参数标记来指示稍后在执行时将数据值绑定到查询的位置。该
?字符不应引号括起来,即使你打算将它们绑定到字符串值。参数标记只能用于出现数据值的地方,而不能用于SQL关键字,标识符等等。
如果具有给定名称的准备好的语句已经存在,则在准备新语句之前隐式地释放它。这意味着如果新语句包含错误并且无法准备,则会返回错误,并且不存在具有给定名称的语句。
准备好的声明的范围是创建它的会话,其中包含以下几个含义:
在一个会话中创建的预备声明不适用于其他会话。
当会话结束时,无论是正常还是异常,其已准备好的语句都不再存在。如果启用自动重新连接,则不会通知客户端连接丢失。出于这个原因,客户可能希望禁用自动重新连接。请参见第27.8.2节“C API自动重新连接控制”。
在存储程序中创建的预备语句在程序执行完成后继续存在,并且可以稍后在程序之外执行。
在存储的程序上下文中准备的语句不能引用存储过程或函数参数或局部变量,因为它们在程序结束时超出范围,并且将在程序之后稍后执行的语句不可用。作为一种解决方法,请参阅用户定义的变量,该变量也具有会话范围; 请参见 第9.4节“用户定义的变量”。
EXECUTEstmt_name[使用@var_name[,@var_name] ...]
在准备一份陈述之后
PREPARE,您可以使用EXECUTE引用准备好的陈述名称的陈述来执行
陈述。如果准备好的语句包含任何参数标记,则必须提供一个USING
列出包含要绑定到参数的值的用户变量的子句。参数值只能由用户变量提供,并且USING子句必须与语句中参数标记的数目完全相同。
您可以多次执行给定的预处理语句,将不同的变量传递给它,或者在每次执行之前将变量设置为不同的值。
有关示例,请参见 第13.5节“准备好的SQL语句语法”。
{DEALLOCATE | DROP} PREPAREstmt_name
要释放一个已准备好的语句
PREPARE,请使用
DEALLOCATE PREPARE引用准备好的语句名称的语句。试图在释放它之后执行预备语句会导致错误。如果创建的准备语句过多,而且DEALLOCATE PREPARE语句或会话结束时未释放,则可能会遇到max_prepared_stmt_count
系统变量强制执行的上限。
有关示例,请参见 第13.5节“准备好的SQL语句语法”。
本节介绍BEGIN ... END
可用于存储程序主体的复合语句和其他语句的语法
:存储过程和函数,触发器和事件。这些对象是根据存储在服务器上供以后调用的SQL代码定义的(请参见
第23章,存储程序和视图)。
复合语句是一个可以包含其他块的块; 变量声明,条件处理程序和游标; 和流程控制结构,如循环和条件测试。
[begin_label:] BEGIN [statement_list] END [end_label]
BEGIN ... END
语法用于编写复合语句,它可以出现在存储程序(存储过程和函数,触发器和事件)中。复合语句可以包含多个语句,由关键字BEGIN和
END关键字包围。
statement_list表示一个或多个语句的列表,每个语句由分号(;)语句分隔符终止。它
statement_list本身是可选的,所以空的复合语句(BEGIN END)是合法的。
BEGIN ... END
块可以嵌套。
使用多个语句要求客户端能够发送包含;语句分隔符的语句字符串。在mysql命令行客户端中,这是通过该delimiter命令处理的。更改;语句结束分隔符(例如,//)允许;在程序主体中使用。有关示例,请参见
第23.1节“定义存储的程序”。
一个BEGIN ...
END块可以被标记。请参见
第13.6.2节“语句标签语法”。
可选[NOT] ATOMIC子句不受支持。这意味着在指令块的开始处没有设置事务保存点,并且BEGIN在此上下文中使用的
子句对当前事务没有影响。
在所有存储的程序中,解析器都将
BEGIN [WORK]
视为BEGIN ...
END块的开始
。要在此上下文中开始交易,请START
TRANSACTION改为使用
。
[begin_label:] BEGIN [statement_list] END [end_label] [begin_label:] LOOPstatement_listEND LOOP [end_label] [begin_label:]重复statement_list直到search_conditionEND REPEAT [end_label] [begin_label:] WHILEsearch_conditionDOstatement_listEND WHILE [end_label]
标签被允许
BEGIN ... END
块和对LOOP,
REPEAT和
WHILE语句。这些语句的标签使用遵循以下规则:
begin_label 必须跟一个冒号。
begin_label可以没有
end_label。如果
end_label存在,它必须与之相同begin_label。
end_label不能没有
begin_label。
相同嵌套级别的标签必须是不同的。
标签最长可以有16个字符。
要引用标签结构中的标签,请使用
ITERATE或
LEAVE语句。以下示例使用这些语句继续迭代或终止循环:
CREATE PROCEDURE doiterate(p1 INT)
开始
label1:LOOP
SET p1 = p1 + 1;
IF p1 <10然后ITERATE label1; 万一;
LEAVE label1;
END LOOP label1;
结束;
块标签的范围不包括块内声明的处理程序的代码。有关细节,请参见 第13.6.7.2节“DECLARE ... HANDLER语法”。
该DECLARE声明用于定义程序本地的各种项目:
局部变量。请参见 第13.6.4节“存储程序中的变量”。
条件和处理程序。请参见 第13.6.7节“条件处理”。
光标。请参见第13.6.6节“光标”。
DECLARE只允许在
BEGIN ... END
复合语句中使用,并且必须在其开始之前,在任何其他语句之前。
声明必须遵循特定的顺序。游标声明必须出现在处理程序声明之前。变量和条件声明必须出现在游标或处理程序声明之前。
系统变量和用户定义的变量可以在存储程序中使用,就像它们可以在存储程序上下文中使用一样。另外,存储的程序可以DECLARE用来定义局部变量,并且可以声明存储的例程(过程和函数)来获取在例程与其调用者之间传递值的参数。
要声明本地变量,请使用该
DECLARE
语句,如
第13.6.4.1节“本地变量DECLARE语法”中所述。
变量可以直接用SET
语句设置
。请参见第13.7.4.1节“变量赋值的SET语法”。
查询结果可以使用或通过打开游标和使用
来检索到局部变量中。请参见
第13.2.9.1节“SELECT ... INTO语法”和第13.6.6节“光标”。
SELECT ...
INTO var_listFETCH ... INTO
var_list
有关本地变量范围以及MySQL如何解析模糊名称的信息,请参见 第13.6.4.2节“本地变量范围和解析”。
不允许将该值分配DEFAULT
给存储过程或函数参数或存储的程序局部变量(例如,使用
语句)。在MySQL 5.7中,这会导致语法错误。
SET
var_name = DEFAULT
DECLAREvar_name[,var_name] ...type[DEFAULTvalue]
该语句在存储的程序中声明局部变量。要为变量提供默认值,请包含一个
DEFAULT子句。该值可以被指定为一个表达式; 它不一定是一个常数。如果该
DEFAULT子句缺失,则初始值为NULL。
就数据类型和溢出检查而言,局部变量被视为存储的例程参数。请参见 第13.1.16节“CREATE PROCEDURE和CREATE FUNCTION语法”。
变量声明必须出现在游标或处理程序声明之前。
局部变量名称不区分大小写。允许的字符和引用规则与其他标识符相同,如第9.2节“模式对象名称”中所述。
局部变量的范围是BEGIN ...
END其声明的
块。变量可以在嵌套在声明块中的块中引用,除了声明具有相同名称的变量的块之外。
有关变量声明的示例,请参见 第13.6.4.2节“本地变量范围和分辨率”。
局部变量的范围是BEGIN ...
END其声明的
块。变量可以在嵌套在声明块中的块中引用,除了声明具有相同名称的变量的块之外。
因为局部变量仅在存储程序执行期间处于作用域中,所以在存储程序中创建的预处理语句中不允许对它们进行引用。准备好的语句范围是当前会话,而不是存储的程序,因此语句可以在程序结束后执行,此时变量将不再处于范围内。例如,
不能用作准备好的声明。这个限制也适用于存储过程和函数参数。请参见
第13.5.1节“PREPARE语法”。
SELECT ... INTO
local_var
一个局部变量不应该与表格列具有相同的名称。如果一条SQL语句(如
SELECT ...
INTO语句)包含对同名的列和声明局部变量的引用,则MySQL当前将该引用解释为变量的名称。考虑下面的过程定义:
CREATE PROCEDURE sp1(x VARCHAR(5))
开始
DECLARE xname VARCHAR(5)DEFAULT'bob';
DECLARE newname VARCHAR(5);
DECLARE xid INT;
SELECT xname,id INTO newname,xid
FROM table1 WHERE xname = xname;
选择新名称;
结束;
MySQL xname在
SELECT语句中将其解释为对xname 变量的引用
而不是xname
列。因此,在sp1()调用过程时
,
无论列newname的值'bob'如何,
变量都会返回值
table1.xname。
同样,以下过程中的游标定义包含一个SELECT引用的语句xname。MySQL将其解释为对该名称的变量的引用,而不是列引用。
CREATE PROCEDURE sp2(x VARCHAR(5))
开始
DECLARE xname VARCHAR(5)DEFAULT'bob';
DECLARE newname VARCHAR(5);
DECLARE xid INT;
DECLARE done TINYINT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT xname,id FROM table1;
为未找到的设置声明CONTINUE HANDLER done = 1;
OPEN cur1;
read_loop:LOOP
FETCH FROM cur1 INTO newname,xid;
如果完成,则退出read_loop; 万一;
选择新名称;
END LOOP;
关闭cur1;
结束;
MySQL的支持IF,
CASE,
ITERATE,
,
,并
构建了存储程序中的流量控制。它也支持
存储的功能。
LEAVE
LOOPWHILEREPEATRETURN
这些结构中的很多都包含其他语句,如以下各节中的语法规范所示。这样的构造可以嵌套。例如,一个
IF语句可能包含一个
WHILE循环,它本身包含一个
CASE语句。
MySQL不支持FOR循环。
CASEcase_valueWHENwhen_valueTHENstatement_list[WHENwhen_valueTHENstatement_list] ... [ELSEstatement_list] END CASE
要么:
案件
WHEN search_conditionTHEN statement_list
[WHEN search_conditionTHEN statement_list] ...
[ELSE statement_list]
END CASE
CASE存储程序
的语句实现了一个复杂的条件结构。
还有一个表达式,它与此处所述的表述不同
。参见
第12.4节“控制流量功能”。该
声明不能有一个
子句,并且它以终止
而不是。
CASE
CASE
CASEELSE NULLEND CASEEND
对于第一种语法,case_value是一个表达式。将该值与when_value每个WHEN子句中的表达式进行
比较,
直到其中一个值相等。当when_value找到相等时,相应的THEN子句
statement_list执行。如果不
when_value相等,则该
ELSE子句
statement_list执行,如果有的话。
此语法不能用于测试是否等于
NULL因为NULL = NULL
是false。请参见第3.3.4.6节“使用NULL值”。
对于第二种语法,将评估每个WHEN子句
search_condition表达式,直到其中一个为真,此时它的相应
THEN子句
statement_list执行。如果不
search_condition相等,则该
ELSE子句
statement_list执行,如果有的话。
如果否when_value或
search_condition匹配测试值并且CASE语句不包含任何ELSE子句,则CASE语句错误结果中找不到Case。
每个statement_list由一个或多个SQL语句组成; 一个空的
statement_list是不允许的。
要处理没有任何值与任何WHEN子句匹配的情况
,请使用ELSE
包含空白
BEGIN ...
END块的情况,如本例中所示。(这里使用的缩进ELSE只是为了清楚起见,并不重要。)
DELIMITER |
CREATE PROCEDURE p()
开始
DECLARE v INT默认值1;
CASE v
WHEN 2 THEN SELECT v;
当3然后选择0;
其他
开始
结束;
END CASE;
结束;
|
如果search_condition那么statement_list[ELSEIFsearch_conditionTHENstatement_list] ... [ELSEstatement_list] 万一
IF存储程序
的语句实现了一个基本的条件构造。
还有一个功能,它不同于此处所述的
说明。参见
第12.4节“控制流量功能”。该
声明可以有
,和
子句,并以此结束
。
IF()
IF
IFTHENELSEELSEIFEND IF
如果search_condition评估结果为true,则执行相应的THEN或
ELSEIF子句
statement_list。如果不
search_condition匹配,则
ELSE子句
statement_list执行。
每个statement_list由一个或多个SQL语句组成; 一个空的
statement_list是不允许的。
与IF ... END IF存储程序中使用的所有其他流程控制块一样,块必须以分号结尾,如下例所示:
DELIMITER //
CREATE FUNCTION SimpleCompare(n INT,m INT)
RETURNS VARCHAR(20)
开始
DECLARE s VARCHAR(20);
IF n> m THEN SET s ='>';
ELSEIF n = m THEN SET s ='=';
ELSE SET s ='<';
万一;
SET s = CONCAT(n,'',s,'',m);
返回s;
结束 //
DELIMITER;
与其他流程控制结构一样,IF ... END
IF块可以嵌套在其他流程控制结构中,包括其他IF
语句。每一个都IF必须由它自己END IF后跟一个分号来终止。您可以使用缩进来使嵌套流控块更容易被人读取(尽管这不是MySQL所要求的),如下所示:
DELIMITER //
CREATE FUNCTION VerboseCompare(n INT,m INT)
RETURNS VARCHAR(50)
开始
DECLARE s VARCHAR(50);
IF n = m THEN SET s ='equals';
其他
如果n> m那么设置s ='更大';
ELSE SET s ='less';
万一;
SET s = CONCAT('is',s,'than');
万一;
SET s = CONCAT(n,'',s,'',m,'。');
返回s;
结束 //
DELIMITER;
在这个例子中,内部IF只有在n不等于
时才被评估m。
离开 label
此语句用于退出具有给定标签的流控制结构。如果标签用于最外面存储的程序块,则LEAVE退出该程序。
LEAVE可以内使用
BEGIN ...
END或循环结构(LOOP,
REPEAT,
WHILE)。
有关示例,请参见第13.6.5.5节“LOOP语法”。
[begin_label:] LOOPstatement_listEND LOOP [end_label]
LOOP实现了一个简单的循环结构,可以重复执行语句列表,它由一个或多个语句组成,每个语句以分号(;)语句分隔符结尾。重复循环内的语句,直到循环结束。通常,这是通过LEAVE声明完成的
。在存储的函数内,RETURN也可以使用,完全退出函数。
忽略包含循环终止语句会导致无限循环。
一个LOOP声明可以被标记。有关标签使用的规则,请参见
第13.6.2节“语句标签语法”。
例:
CREATE PROCEDURE doiterate(p1 INT)
开始
label1:LOOP
SET p1 = p1 + 1;
IF p1 <10 THEN
ITERATE label1;
万一;
LEAVE label1;
END LOOP label1;
SET @x = p1;
结束;
[begin_label:]重复statement_list直到search_conditionEND REPEAT [end_label]
REPEAT重复
一个语句中的语句列表,
直到search_condition表达式为真。因此,a REPEAT总是至少进入一次循环。
statement_list由一个或多个语句组成,每个语句由分号(;)语句分隔符终止。
一个REPEAT声明可以被标记。有关标签使用的规则,请参见
第13.6.2节“语句标签语法”。
例:
MySQL的>delimiter //mysql>CREATE PROCEDURE dorepeat(p1 INT)- >BEGIN- >SET @x = 0;- >REPEAT- >SET @x = @x + 1;- >UNTIL @x > p1 END REPEAT;- >END- >//查询OK,0行受影响(0.00秒) MySQL的>CALL dorepeat(1000)//查询OK,0行受影响(0.00秒) MySQL的>SELECT @x//+ ------ + | @x | + ------ + | 1001 | + ------ + 一排(0.00秒)
返回 expr
该RETURN语句终止存储函数的执行并将该值返回
expr给函数调用方。RETURN
存储的函数中至少有一条语句。如果函数有多个出口点,可能会有多个。
此语句不用于存储过程,触发器或事件。该LEAVE语句可用于退出这些类型的存储程序。
[begin_label:] WHILEsearch_conditionDOstatement_listEND WHILE [end_label]
WHILE
只要search_condition表达式为真
,语句中的语句列表就会重复
。
statement_list由一个或多个SQL语句组成,每个SQL语句以分号(;)语句分隔符结尾。
一个WHILE声明可以被标记。有关标签使用的规则,请参见
第13.6.2节“语句标签语法”。
例:
CREATE PROCEDURE dowhile()
开始
DECLARE v1 INT DEFAULT 5;
WHILE v1> 0 DO
...
SET v1 = v1 - 1;
END WHILE;
结束;
MySQL支持存储程序中的游标。语法与嵌入式SQL中的一样。游标具有以下属性:
敏感性:服务器可能会或不会制作其结果表的副本
只读:不可更新
不可滚动:只能在一个方向上移动,不能跳过行
游标声明必须出现在处理程序声明之前以及变量和条件声明之后。
例:
CREATE PROCEDURE curdemo()
开始
DECLARE完成了INT DEFAULT FALSE;
宣布CHAR(16);
DECLARE b,c INT;
DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
为未找到的设置DECLARE CONTINUE HANDLER done = TRUE;
OPEN cur1;
OPEN cur2;
read_loop:LOOP
FETCH cur1 INTO a,b;
FETCH cur2 INTO c;
如果完成了
LEAVE read_loop;
万一;
如果b <c那么
INSERT INTO test.t3 VALUES(a,b);
其他
INSERT INTO test.t3 VALUES(a,c);
万一;
END LOOP;
关闭cur1;
关闭cur2;
结束;
关 cursor_name
该语句关闭以前打开的光标。有关示例,请参见第13.6.6节“光标”。
如果光标未打开,则会发生错误。
如果未明确关闭BEGIN ...
END,则在声明块的末尾关闭游标
。
为...声明cursor_nameCURSORselect_statement
该语句声明一个游标并将其与一个SELECT用于检索要由游标遍历的行的语句相关联
。要稍后获取行,请使用FETCH语句。SELECT语句检索的列数
必须与语句中指定的输出变量数相匹配
FETCH。
该SELECT声明不能有一个INTO条款。
游标声明必须出现在处理程序声明之前以及变量和条件声明之后。
存储的程序可能包含多个游标声明,但在给定块中声明的每个游标必须具有唯一的名称。有关示例,请参见第13.6.6节“光标”。
对于通过SHOW语句提供的信息
,在很多情况下可以通过使用带有INFORMATION_SCHEMA表格的游标来获得等效信息。
FETCH [[NEXT] FROM]cursor_nameINTOvar_name[,var_name] ...
该语句读取SELECT与指定游标(必须打开)关联的语句的下一行
,并前进游标指针。如果存在一行,则提取的列将存储在命名变量中。该列检索的列数
SELECT语句必须与语句中指定的输出变量数相匹配
FETCH。
如果没有更多行可用,则使用SQLSTATE值会发生无数据条件'02000'。为了检测这种情况,你可以为它设置一个处理程序(或者为一个
NOT FOUND条件)。有关示例,请参见
第13.6.6节“光标”。
请注意,另一个操作(如a
SELECT或另一个操作FETCH)也可能会导致处理程序通过提高相同的条件来执行。如果有必要区分哪种操作引发了这种情况,请将操作放在其自己的
BEGIN ...
END块中,以便它可以与自己的处理程序关联。
存储程序执行期间可能会出现需要特殊处理的条件,例如退出当前程序块或继续执行。处理程序可以定义为一般条件,如警告或异常,或针对特定条件(如特定的错误代码)。特定的条件可以分配名称并在处理程序中以这种方式提及。
要命名一个条件,请使用该
DECLARE ...
CONDITION语句。要声明处理程序,请使用该
DECLARE ...
HANDLER语句。请参见
第13.6.7.1节“DECLARE ... CONDITION语法”和
第13.6.7.2节“DECLARE ... HANDLER语法”。有关条件发生时服务器如何选择处理程序的信息,请参见
第13.6.7.6节“处理程序的作用域规则”。
要提出条件,请使用该
SIGNAL语句。要修改条件处理程序中的条件信息,请使用
RESIGNAL。请参见
第13.6.7.1节“DECLARE ... CONDITION语法”和
第13.6.7.2节“DECLARE ... HANDLER语法”。
要从诊断区域检索信息,请使用该
GET DIAGNOSTICS语句(请参见
第13.6.7.3节“GET DIAGNOSTICS语法”)。有关诊断区域的信息,请参见第13.6.7.7节“MySQL诊断区域”。
为...声明DECLAREcondition_name条件condition_valuecondition_value:mysql_error_code| SQLSTATE [VALUE]sqlstate_value
该DECLARE
... CONDITION语句声明了一个命名错误条件,将名称与需要特定处理的条件关联起来。该名称可以在随后的DECLARE ...
HANDLER语句中引用
(请参见
第13.6.7.2节“DECLARE ... HANDLER语法”)。
条件声明必须出现在游标或处理程序声明之前。
该condition_value用于
DECLARE ...
CONDITION指示条件与条件名称关联的特定条件或类。它可以采取以下形式:
mysql_error_code:一个表示MySQL错误代码的整数字面值。
不要使用MySQL错误代码0,因为它表示成功,而不是错误条件。有关MySQL错误代码的列表,请参见第B.3节“服务器错误代码和消息”。
SQLSTATE [VALUE] sqlstate_value:表示SQLSTATE值的5个字符的字符串文字。
不要使用以开头的SQLSTATE值,'00'因为这些值
指示成功而不是错误条件。有关SQLSTATE值的列表,请参见第B.3节“服务器错误代码和消息”。
引用SIGNAL或使用
RESIGNAL语句中的条件名称
必须与SQLSTATE值关联,而不是MySQL错误代码。
使用条件名称可以帮助使存储的程序代码更加清晰。例如,此处理程序适用于尝试删除不存在的表,但只有在您知道1051是“ 未知表 ”的MySQL错误代码时才会显示此消息:
为1051声明继续处理程序
开始
- 处理者的身体
结束;
通过为条件声明一个名称,更容易看到处理程序的目的:
声明no_such_table条件1051;
为no_such_table声明继续处理程序
开始
- 处理者的身体
结束;
以下是针对相同条件的命名条件,但是基于相应的SQLSTATE值而不是MySQL错误代码:
为SQLSTATE'42S02'声明no_such_table CONDITION;
为no_such_table声明继续处理程序
开始
- 处理者的身体
结束;
DECLAREhandler_actionHANDLER FORcondition_value[,condition_value] ...statementhandler_action: 继续 | 出口 | UNDOcondition_value:mysql_error_code| SQLSTATE [VALUE]sqlstate_value|condition_name| SQLWARNING | 未找到 | SQLEXCEPTION
该DECLARE ...
HANDLER语句指定处理一个或多个条件的处理程序。如果发生这些情况之一,则statement执行指定。
statement可以是一个简单的语句,或者使用和
编写的复合语句(参见第13.6.1节“BEGIN ... END复合语句语法”)。
SET var_name =
valueBEGINEND
处理程序声明必须出现在变量或条件声明之后。
该handler_action值指示处理程序在执行处理程序语句后执行的操作:
CONTINUE:继续执行当前程序。
EXIT:执行终止于BEGIN ...
END声明处理程序的
复合语句。即使条件出现在内部块中也是如此。
UNDO: 不支持。
的condition_value用于
DECLARE ...
HANDLER表明激活处理程序中的特定条件或一类的条件。它可以采取以下形式:
mysql_error_code:表示MySQL错误代码的整数字面值,如1051指定“ 未知表 ”:
为1051声明继续处理程序
开始
- 处理者的身体
结束;
不要使用MySQL错误代码0,因为它表示成功,而不是错误条件。有关MySQL错误代码的列表,请参见第B.3节“服务器错误代码和消息”。
SQLSTATE [VALUE] sqlstate_value:表示SQLSTATE值的5个字符的字符串文字,例如'42S01'指定“ 未知表 ”:
为SQLSTATE'42S02'声明CONTINUE HANDLER
开始
- 处理者的身体
结束;
不要使用以开头的SQLSTATE值,'00'因为这些值
指示成功而不是错误条件。有关SQLSTATE值的列表,请参见第B.3节“服务器错误代码和消息”。
condition_name:之前指定的条件名称
DECLARE
... CONDITION。条件名称可以与MySQL错误代码或SQLSTATE值关联。请参见
第13.6.7.1节“DECLARE ... CONDITION语法”。
SQLWARNING:以开头的SQLSTATE类的速记'01'。
为SQLWARNING声明CONTINUE HANDLER
开始
- 处理者的身体
结束;
NOT FOUND:以开头的SQLSTATE类的速记'02'。这在游标的上下文中是相关的,用于控制当游标到达数据集的末尾时发生的情况。如果没有更多行可用,则使用SQLSTATE值会发生无数据条件'02000'。为了检测这种情况,你可以为它设置一个处理程序或一个NOT FOUND条件。
声明未找到继续处理程序
开始
- 处理者的身体
结束;
又如,请参见第13.6.6节“光标”。NOT FOUND对于不检索行的语句也会发生此
情况
。
SELECT ... INTO
var_list
SQLEXCEPTION:不以'00'“ '01',”或“
'02'。” 开头的SQLSTATE类的速记
。
声明SQLEXCEPTION的继续处理程序
开始
- 处理者的身体
结束;
有关条件发生时服务器如何选择处理程序的信息,请参见第13.6.7.6节“处理程序的作用域规则”。
如果发生没有声明处理程序的情况,则采取的操作取决于条件类:
下面的示例使用处理程序来处理SQLSTATE
'23000'重复键错误:
MySQL的>CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));查询OK,0行受影响(0.00秒) MySQL的>delimiter //mysql>CREATE PROCEDURE handlerdemo ()- >BEGIN- >DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;- >SET @x = 1;- >INSERT INTO test.t VALUES (1);- >SET @x = 2;- >INSERT INTO test.t VALUES (1);- >SET @x = 3;- >END;- >//查询OK,0行受影响(0.00秒) MySQL的>CALL handlerdemo()//查询OK,0行受影响(0.00秒) MySQL的>SELECT @x//+ ------ + | @x | + ------ + | 3 | + ------ + 一排(0.00秒)
请注意,该过程@x是3在执行过程之后进行的,该过程显示在错误发生后继续执行过程的结束。如果
DECLARE ...
HANDLER语句不存在,MySQL将EXIT在第二次INSERT因PRIMARY KEY约束而失败后采取默认操作(),并
SELECT @x返回
2。
要忽略一个条件,CONTINUE
为它声明一个处理程序并将其与一个空白块相关联。例如:
为SQLWARNING开始DECLARE CONTINUE HANDLER BEGIN END;
块标签的范围不包括块内声明的处理程序的代码。因此,与处理程序关联的语句不能使用
ITERATE或
LEAVE引用包含处理程序声明的块的标签。考虑下面的例子,
REPEAT块有一个标签
retry:
CREATE PROCEDURE p()
开始
声明INT DEFAULT 3;
重试:
重复
开始
为SQLWARNING声明CONTINUE HANDLER
开始
ITERATE重试; #非法
结束;
如果我<0那么
LEAVE重试; #合法
万一;
SET i = i - 1;
结束;
直到错误结束重复;
结束;
该retry标签
IF在该块内的语句的范围内。它不在CONTINUE处理程序的范围内,因此引用无效并导致错误:
错误1308(42000):LEAVE没有匹配的标签:重试
要避免在处理程序中引用外部标签,请使用以下策略之一:
要离开该块,请使用EXIT处理程序。如果不需要块清理,则
BEGIN ...
END处理程序主体可以是空的:
DECLARE退出SQLWARNING开始处理程序结束;
否则,将清理语句放在处理程序体中:
用于SQLWARNING的DECLARE EXIT HANDLER
开始
block cleanup statements
结束;
要继续执行,CONTINUE可以在可以在封闭块中检查的处理程序中设置状态变量,
以确定是否调用处理程序。以下示例done用于此目的的变量
:
CREATE PROCEDURE p()
开始
声明INT DEFAULT 3;
DECLARE完成了INT DEFAULT FALSE;
重试:
重复
开始
为SQLWARNING声明CONTINUE HANDLER
开始
SET done = TRUE;
结束;
如果完成或我<0那么
LEAVE重试;
万一;
SET i = i - 1;
结束;
直到错误结束重复;
结束;
GET [CURRENT | 堆叠]诊断
{
statement_information_item
[,statement_information_item] ...
| 条件
[,] ...condition_number
condition_information_itemcondition_information_item
}
statement_information_item:
target=statement_information_item_name
condition_information_item:
target=condition_information_item_name
statement_information_item_name:
数
| ROW_COUNT
condition_information_item_name:
CLASS_ORIGIN
| SUBCLASS_ORIGIN
| RETURNED_SQLSTATE
| MESSAGE_TEXT
| MYSQL_ERRNO
| CONSTRAINT_CATALOG
| CONSTRAINT_SCHEMA
| CONSTRAINT_NAME
| CATALOG_NAME
| SCHEMA_NAME
| TABLE_NAME
| COLUMN_NAME
| CURSOR_NAME
condition_number,target:
(见下面的讨论)
SQL语句生成填充诊断区域的诊断信息。该GET
DIAGNOSTICS声明使应用程序能够检查这些信息。(您也可以使用SHOW
WARNINGS或SHOW ERRORS
查看条件或错误。)
没有特殊的特权需要执行
GET DIAGNOSTICS。
关键字CURRENT意味着从当前诊断区域检索信息。关键字
STACKED表示从第二诊断区域检索信息,只有当前上下文是条件处理程序时才可用。如果没有给出关键字,则默认使用当前的诊断区域。
该GET DIAGNOSTICS语句通常用于存储程序中的处理程序。它是一个GET [CURRENT]
DIAGNOSTICS允许外部处理程序上下文检查任何SQL语句执行情况的MySQL扩展
。例如,如果您调用mysql客户端程序,则可以在提示符处输入以下语句:
MySQL的>DROP TABLE test.no_such_table;错误1051(42S02):未知表'test.no_such_table' mysql>GET DIAGNOSTICS CONDITION 1- >@p1 = RETURNED_SQLSTATE, @p2 = MESSAGE_TEXT;mysql>SELECT @p1, @p2;+ ------- + ------------------------------------ + | @ p1 | @ p2 | + ------- + ------------------------------------ + | 42S02 | 未知表'test.no_such_table'| + ------- + ------------------------------------ +
该扩展仅适用于当前的诊断区域。它不适用于第二个诊断区域,因为
GET STACKED DIAGNOSTICS仅当当前上下文是条件处理程序时才被允许。如果不是这种情况,GET STACKED DIAGNOSTICS when handler not
active则会发生错误。
有关诊断区域的说明,请参见 第13.6.7.7节“MySQL诊断区域”。简而言之,它包含两种信息:
声明信息,例如发生的条件数量或受影响的行数。
状态信息,如错误代码和消息。如果一个语句提出了多个条件,诊断区域的这个部分每个都有一个条件区域。如果语句没有提供任何条件,则诊断区域的这部分是空的。
对于产生三个条件的语句,诊断区域包含像这样的语句和条件信息:
声明信息:
行数
...其他声明信息项目...
条件区域列表:
条件1:
条件1的错误代码
条件1的错误消息
...其他条件信息项目...
条件2:
条件2的错误代码:
条件2的错误消息
...其他条件信息项目...
条件3:
条件3的错误代码
条件3的错误消息
...其他条件信息项目...
GET DIAGNOSTICS 可以获得声明或条件信息,但不能同时在两个语句中使用:
要获取语句信息,请将所需的语句项目检索到目标变量中。此实例
GET DIAGNOSTICS将可用条件的数量和受行影响的计数分配给用户变量,@p1并且
@p2:
GET DIAGNOSTICS @ p1 = NUMBER,@ p2 = ROW_COUNT;
要获取条件信息,请指定条件编号并将所需的条件项检索到目标变量中。此实例GET
DIAGNOSTICS将SQLSTATE值和错误消息分配给用户变量@p3并
@p4:
获取诊断条件1 @ p3 = RETURNED_SQLSTATE,@ p4 = MESSAGE_TEXT;
检索列表指定一个或多个
分配,用逗号分隔。每个赋值都会命名一个目标变量和一个
或
指示符,具体取决于该语句是检索语句还是条件信息。
target =
item_namestatement_information_item_namecondition_information_item_name
target用于存储项目信息的
有效指示符可以是存储过程或函数参数,存储的用DECLARE或声明的程序局部变量
或用户定义的变量。
有效的condition_number指示符可以是存储过程或函数参数,存储DECLARE用户定义变量,系统变量或文字声明的程序局部变量
。字符文字可能包括
_charset介绍人。如果条件编号不在从1到具有信息的条件区域数量的范围内,则会发生警告。在这种情况下,将警告添加到诊断区域而不清除它。
当条件发生时,MySQL不会填充所有可识别的条件项GET
DIAGNOSTICS。例如:
mysql>GET DIAGNOSTICS CONDITION 1- >@p5 = SCHEMA_NAME, @p6 = TABLE_NAME;mysql>SELECT @p5, @p6;+ ------ + ------ + | @ p5 | @ p6 | + ------ + ------ + | | | + ------ + ------ +
在标准SQL中,如果有多个条件,则第一个条件与SQLSTATE前一个SQL语句返回的值相关。在MySQL中,这是不能保证的。要获得主要的错误,你不能这样做:
GET DIAGNOSTICS CONDITION 1 @errno = MYSQL_ERRNO;
相反,首先检索条件计数,然后使用它来指定要检查的条件编号:
GET DIAGNOSTICS @cno = NUMBER; GET DIAGNOSTICS CONDITION @cno @errno = MYSQL_ERRNO;
有关允许的语句和条件信息项目以及在条件发生时填充哪些项目的信息,请参见 第13.6.7.7.2节“诊断区域信息项目”。
下面是一个示例,它使用GET
DIAGNOSTICS存储过程上下文中的异常处理程序来评估插入操作的结果。如果插入成功,则该过程用于
GET DIAGNOSTICS获取受行影响的计数。这表明,GET DIAGNOSTICS只要当前的诊断区域未被清除,您可以多次使用它
来检索有关语句的信息。
CREATE PROCEDURE do_insert(value INT)
开始
- 声明变量以保存诊断区域信息
DECLARE代码CHAR(5)DEFAULT'00000';
DECLARE msg TEXT;
DECLARE行INT;
DECLARE结果TEXT;
- 声明失败插入的异常处理程序
声明SQLEXCEPTION的继续处理程序
开始
获取诊断条件1
code = RETURNED_SQLSTATE,msg = MESSAGE_TEXT;
结束;
- 执行插入
INSERT INTO t1(int_col)VALUES(value);
- 检查插入是否成功
IF code ='00000'THEN
GET DIAGNOSTICS rows = ROW_COUNT;
SET结果= CONCAT('insert succeeded,row count =',rows);
其他
SET result = CONCAT('insert failed,error =',code,',message =',msg);
万一;
- 说出发生了什么事
SELECT结果;
结束;
假设这t1.int_col是一个声明为的整数列NOT NULL。该过程在被调用时分别插入非值NULL和NULL值时产生这些结果:
MySQL的>CALL do_insert(1);+ --------------------------------- + | 结果| + --------------------------------- + | 插入成功,行计数= 1 | + --------------------------------- + MySQL的>CALL do_insert(NULL);+ ------------------------------------------------- ------------------------ + | 结果| + ------------------------------------------------- ------------------------ + | 插入失败,错误= 23000,message =列'int_col'不能为空| + ------------------------------------------------- ------------------------ +
当条件处理程序激活时,会发生对诊断区域堆栈的推送:
第一个(当前)诊断区域将成为第二个(堆叠)诊断区域,并将创建一个新的当前诊断区域作为其副本。
GET
[CURRENT] DIAGNOSTICS并且
GET STACKED
DIAGNOSTICS可以在处理程序中用于访问当前和堆叠的诊断区域的内容。
最初,两个诊断区域都会返回相同的结果,因此只要您在处理程序中执行任何更改其当前诊断区域的语句,就可以从当前诊断区域获取有关激活处理程序的条件的信息。
但是,处理程序内执行的语句可以修改当前诊断区域,根据正常规则清除和设置其内容(请参见 第13.6.7.7.3节“如何填充诊断区域”)。
获取处理程序激活条件信息的更可靠的方法是使用堆栈式诊断区域,除了在处理程序内执行的语句无法修改该诊断区域
RESIGNAL。有关当前诊断区域的设置和清除时间的信息,请参见第13.6.7.7节“MySQL诊断区域”。
下一个示例显示了GET STACKED
DIAGNOSTICS即使在处理程序语句修改了当前的诊断区域之后,如何在处理程序中使用它以获取有关处理的异常的信息。
在存储过程中p(),我们尝试将两个值插入包含TEXT NOT
NULL列的表中。第一个值是非NULL字符串,第二个值是
NULL。该列禁止
NULL值,所以第一次插入成功,但第二次导致异常。该过程包含一个异常处理程序,用于映射尝试插入
NULL空字符串的插入操作:
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(c1 TEXT NOT NULL);
DROP程序如果存在p;
分隔符//
CREATE PROCEDURE p()
开始
- 声明变量以保存诊断区域信息
DECLARE errcount INT;
DECLARE errno INT;
DECLARE msg TEXT;
DECLARE退出处理器以处理SQLEXCEPTION
开始
- 这里的当前DA非空,因为没有事先陈述
- 在处理程序中执行已清除它
获取当前的诊断条件1
errno = MYSQL_ERRNO,msg = MESSAGE_TEXT;
在映射插入之前SELECT'当前DA'AS op,errno,msg;
获取堆叠的诊断条件1
errno = MYSQL_ERRNO,msg = MESSAGE_TEXT;
SELECT'堆栈DA映射插入之前'AS op,errno,msg;
- 试图将NULL插入到空字符串插入
INSERT INTO t1(c1)VALUES('');
- 这里当前的DA应该是空的(如果INSERT成功),
- 在尝试之前检查是否有条件
- 获取条件信息
获取当前诊断errcount = NUMBER;
如果errcount = 0
然后
SELECT'映射插入成功,当前DA为空'AS操作;
其他
获取当前的诊断条件1
errno = MYSQL_ERRNO,msg = MESSAGE_TEXT;
SELECT映射插入后的当前DA'AS op,errno,msg;
万一 ;
获取堆叠的诊断条件1
errno = MYSQL_ERRNO,msg = MESSAGE_TEXT;
SELECT'堆栈DA映射后插入'AS op,errno,msg;
结束;
INSERT INTO t1(c1)VALUES('string 1');
INSERT INTO t1(c1)VALUES(NULL);
结束;
//
定界符
CALL p();
SELECT * FROM t1;
当处理程序激活时,将当前诊断区域的副本推送到诊断区域堆栈。处理程序首先显示当前和堆叠的诊断区域的内容,它们最初都是相同的:
+ --------------------------------- + ------- ------- + --------------------- + | op | errno | msg | + --------------------------------- + ------- ------- + --------------------- + | 在映射插入|之前的当前DA 1048 | 列'c1'不能为空| + --------------------------------- + ------- ------- + --------------------- + + --------------------------------- + ------- ------- + --------------------- + | op | errno | msg | + --------------------------------- + ------- ------- + --------------------- + | 在映射插入|之前堆栈DA 1048 | 列'c1'不能为空| + --------------------------------- + ------- ------- + --------------------- +
在语句之后执行的GET
DIAGNOSTICS语句可能会重置当前的诊断区域。语句可能会重置当前的诊断区域。例如,处理程序将NULL
插入映射到空字符串插入并显示结果。新插入成功并清除当前诊断区域,但堆栈诊断区域保持不变,并且仍包含有关激活处理程序的条件的信息:
+ ---------------------------------------------- + | op | + ---------------------------------------------- + | 映射插入成功,当前DA为空| + ---------------------------------------------- + + -------------------------------- + ------- -------- + -------------------- + | op | errno | msg | + -------------------------------- + ------- -------- + -------------------- + | 在映射插入|之后堆栈DA 1048 | 列'c1'不能为空| + -------------------------------- + ------- -------- + -------------------- +
条件处理程序结束时,其当前诊断区域将从堆栈中弹出,堆栈的诊断区域将成为存储过程中的当前诊断区域。
过程返回后,该表包含两行。试图插入NULL映射到空字符串插入的空行
是:
+ ---------- + | c1 | + ---------- + | 字符串1 | | | + ---------- +
在前面的示例中,GET
DIAGNOSTICS条件处理程序中用于从当前和堆栈的诊断区域检索信息的前两条语句返回相同的值。如果重置当前诊断区域的语句在处理程序中较早执行,情况就不会如此。假设将
p()其重写为将
DECLARE语句放在处理程序定义中,而不是在它之前:
CREATE PROCEDURE p()
开始
DECLARE退出处理器以处理SQLEXCEPTION
开始
- 声明变量以保存诊断区域信息
DECLARE errcount INT;
DECLARE errno INT;
DECLARE msg TEXT;
获取当前的诊断条件1
errno = MYSQL_ERRNO,msg = MESSAGE_TEXT;
在映射插入之前SELECT'当前DA'AS op,errno,msg;
获取堆叠的诊断条件1
errno = MYSQL_ERRNO,msg = MESSAGE_TEXT;
SELECT'堆栈DA映射插入之前'AS op,errno,msg;
...
在这种情况下,结果取决于版本:
在MySQL 5.7.2之前,DECLARE
不会更改当前的诊断区域,所以前两个GET DIAGNOSTICS
语句返回相同的结果,就像在原始版本中一样p()。
在MySQL 5.7.2中,完成了工作以确保所有的非诊断语句都按照SQL标准填充诊断区域。DECLARE是其中之一,因此在5.7.2及更高版本中,
DECLARE在处理程序开始处执行的语句将清除当前的诊断区域,并且这些GET
DIAGNOSTICS语句会产生不同的结果:
+ --------------------------------- + ------- + ------ + | op | errno | msg | + --------------------------------- + ------- + ------ + | 在映射插入|之前的当前DA NULL | NULL | + --------------------------------- + ------- + ------ + + --------------------------------- + ------- ------- + --------------------- + | op | errno | msg | + --------------------------------- + ------- ------- + --------------------- + | 在映射插入|之前堆栈DA 1048 | 列'c1'不能为空| + --------------------------------- + ------- ------- + --------------------- +
要在获取激活处理程序的条件信息时避免此情况发生,请务必访问堆栈的诊断区域,而不是当前的诊断区域。
RESIGNAL [condition_value] [SETsignal_information_item[,signal_information_item] ...]condition_value: SQLSTATE [VALUE]sqlstate_value|condition_namesignal_information_item:condition_information_item_name=simple_value_specificationcondition_information_item_name: CLASS_ORIGIN | SUBCLASS_ORIGIN | MESSAGE_TEXT | MYSQL_ERRNO | CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | CATALOG_NAME | SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | CURSOR_NAMEcondition_name,simple_value_specification: (见下面的讨论)
RESIGNAL传递在存储过程或函数,触发器或事件内的复合语句内执行条件处理程序期间可用的错误条件信息。
RESIGNAL在传递信息之前可能会更改部分或全部信息。
RESIGNAL有关
SIGNAL,但,而不是发起条件的SIGNAL
呢,RESIGNAL继电器现有条件信息,有可能修改之后。
RESIGNAL可以处理错误并返回错误信息。否则,通过在处理程序中执行SQL语句,会导致处理程序激活的信息被破坏。
RESIGNAL如果给定的处理程序可以处理部分情况,那么也可以缩短一些程序,然后将条件“ 上线 ”传递给另一个处理程序。
执行RESIGNAL语句不需要特殊权限
。
所有形式都RESIGNAL要求当前上下文成为条件处理程序。否则,
RESIGNAL是非法的,并发生
RESIGNAL when handler not active错误。
要从诊断区域检索信息,请使用该
GET DIAGNOSTICS语句(请参见
第13.6.7.3节“GET DIAGNOSTICS语法”)。有关诊断区域的信息,请参见第13.6.7.7节“MySQL诊断区域”。
对于condition_value和
signal_information_item,定义和规则是相同
RESIGNAL的
SIGNAL。例如,该
值condition_value可以是一个
SQLSTATE值,并且该值可以指示错误,警告或“ 未找到”。“有关更多信息,请参见第13.6.7.5节”SIGNAL语法“。
该RESIGNAL声明将
condition_value和
SET这两个条款,是可选的。这导致了几种可能的用途:
这些用例都会导致诊断和状况区域发生变化:
诊断区域包含一个或多个条件区域。
条件区域包含条件信息项目,例如SQLSTATE值
MYSQL_ERRNO,或
MESSAGE_TEXT。
有一堆诊断区域。当处理程序接受控制时,会将诊断区域推到堆栈的顶部,因此在处理程序执行期间有两个诊断区域:
第一个(当前)诊断区域以最后一个诊断区域的副本开始,但将被更改当前诊断区域的处理程序中的第一条语句覆盖。
最后一个(堆叠的)诊断区域,它具有在处理程序控制之前设置的条件区域。
诊断区域中的最大条件区域数由max_error_count系统变量的值决定
。请参见
第13.6.7.7.5节“与诊断区域相关的系统变量”。
一个简单的RESIGNAL意思就是
“ 不加改变地传递错误。“它恢复上一个诊断区域并使其成为当前的诊断区域。也就是说,它“ 弹出 ”诊断区域堆栈。
在捕获条件的条件处理程序中,一个用于RESIGNAL单独使用是执行一些其他操作,然后在不更改原始条件信息(进入处理程序之前存在的信息)的情况下传递。
例:
DROP TABLE IF EXISTS xx;
分隔符//
CREATE PROCEDURE p()
开始
DECLARE退出处理器以处理SQLEXCEPTION
开始
SET @error_count = @error_count + 1;
IF @a = 0 THEN RESIGNAL; 万一;
结束;
DROP TABLE xx;
结束//
定界符
SET @error_count = 0;
SET @a = 0;
CALL p();
假设该DROP TABLE xx陈述失败。诊断区域堆栈如下所示:
DA 1.错误1051(42S02):未知表'xx'
然后执行进入EXIT处理程序。它首先将诊断区域推到栈顶,现在看起来像这样:
DA 1.错误1051(42S02):未知表'xx' DA 2.错误1051(42S02):未知表'xx'
此时,第一个(当前)和第二个(堆叠的)诊断区域的内容是相同的。第一诊断区域可以通过随后在处理程序中执行的语句进行修改。
过程语句通常会清除第一个诊断区域。BEGIN是一个例外,它不明确,它什么都不做。SET并不是一个例外,它会清除,执行操作,并产生“ 成功 ”的结果。“诊断区域堆栈现在看起来像这样:
DA 1.错误0000(00000):成功操作 DA 2.错误1051(42S02):未知表'xx'
在这一点上,如果@a = 0,
RESIGNAL弹出诊断区栈,它现在看起来是这样的:
DA 1.错误1051(42S02):未知表'xx'
这就是呼叫者所看到的。
如果@a不是0,则处理程序简单地结束,这意味着当前诊断区域(已被“ 处理 ”)不再使用,因此它可以被丢弃,导致堆栈的诊断区域成为当前的诊断区域再次。诊断区域堆栈如下所示:
DA 1.错误0000(00000):成功操作
细节使其看起来很复杂,但最终的结果非常有用:处理程序可以在不破坏引起处理程序激活的条件信息的情况下执行。
RESIGNAL用一个
SET子句提供新的信号信息,所以这个语句意味着“ 随着变化传递错误 ”:
RESIGNAL SETsignal_information_item[,signal_information_item] ...;
与RESIGNAL单独一样,这个想法是弹出诊断区域堆栈,以便原始信息将消失。与RESIGNAL单独不同
,SET条款中指定的任何内容都会发生变化
例:
DROP TABLE IF EXISTS xx;
分隔符//
CREATE PROCEDURE p()
开始
DECLARE退出处理器以处理SQLEXCEPTION
开始
SET @error_count = @error_count + 1;
IF @a = 0 THEN RESIGNAL SET MYSQL_ERRNO = 5; 万一;
结束;
DROP TABLE xx;
结束//
定界符
SET @error_count = 0;
SET @a = 0;
CALL p();
请记住,从前面的讨论中
RESIGNAL可以得出如下诊断区域堆栈:
DA 1.错误1051(42S02):未知表'xx'
这个RESIGNAL SET MYSQL_ERRNO = 5语句的结果代替了调用者看到的内容:
DA 1.错误5(42S02):未知表'xx'
换句话说,它会改变错误号码,而不是别的。
该RESIGNAL声明可以更改任何或所有的信号信息项目,使诊断区域的第一个条件区域看起来完全不同。
RESIGNAL条件值意味着“ 将条件推入当前的诊断区域。“如果该SET条款存在,它也会更改错误信息。
RESIGNALcondition_value[SETsignal_information_item[,signal_information_item] ...];
这种形式RESIGNAL恢复上一个诊断区域,并使其成为当前的诊断区域。也就是说,它会“ 跳出 ”诊断区域堆栈,这与RESIGNAL单独做一个简单的操作相同
。但是,它也会根据条件值或信号信息更改诊断区域。
例:
DROP TABLE IF EXISTS xx;
分隔符//
CREATE PROCEDURE p()
开始
DECLARE退出处理器以处理SQLEXCEPTION
开始
SET @error_count = @error_count + 1;
IF @a = 0 THEN RESIGNAL SQLSTATE'45000'SET MYSQL_ERRNO = 5; 万一;
结束;
DROP TABLE xx;
结束//
定界符
SET @error_count = 0;
SET @a = 0;
SET @@ max_error_count = 2;
CALL p();
SHOW ERRORS;
这与前面的例子类似,并且效果是相同的,除了如果
RESIGNAL发生,当前情况区域在末尾看起来不同。(条件增加而不是替代现有条件的原因是使用条件值。)
该RESIGNAL语句包含一个条件值(SQLSTATE '45000'),因此它添加了一个新的条件区域,导致诊断区域堆栈如下所示:
DA 1.(条件2)ERROR 1051(42S02):未知表'xx'
(条件1)错误5(45000)未知表'xx'
结果CALL
p()和SHOW ERRORS
这个例子是:
MySQL的>CALL p();错误5(45000):未知表'xx' MySQL的>SHOW ERRORS;+ ------- + ------ + ---------------------------------- + | 级别| 代码| 留言| + ------- + ------ + ---------------------------------- + | 错误| 1051 | 未知表'xx'| | 错误| 5 | 未知表'xx'| + ------- + ------ + ---------------------------------- +
所有形式都RESIGNAL要求当前上下文成为条件处理程序。否则,
RESIGNAL是非法的,并发生
RESIGNAL when handler not active错误。例如:
MySQL的>CREATE PROCEDURE p () RESIGNAL;查询OK,0行受影响(0.00秒) MySQL的>CALL p();错误1645(0K000):RESIGNAL处理程序未激活时
这是一个更困难的例子:
分隔符// CREATE FUNCTION f()返回INT 开始 RESIGNAL; 返回5; 结束// CREATE PROCEDURE p() 开始 DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @ a = f(); SIGNAL SQLSTATE'55555'; 结束// 定界符 CALL p();
RESIGNAL在存储的函数内发生f()。虽然f()本身是在EXIT处理程序的上下文中调用的,但
其内部的执行
f()具有自己的上下文,而不是处理程序上下文。因此,RESIGNAL在
“ 处理程序未激活 ”错误的f()结果中。
SIGNALcondition_value[SETsignal_information_item[,signal_information_item] ...]condition_value: SQLSTATE [VALUE]sqlstate_value|condition_namesignal_information_item:condition_information_item_name=simple_value_specificationcondition_information_item_name: CLASS_ORIGIN | SUBCLASS_ORIGIN | MESSAGE_TEXT | MYSQL_ERRNO | CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | CATALOG_NAME | SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | CURSOR_NAMEcondition_name,simple_value_specification: (见下面的讨论)
SIGNAL是
“ 返回 ”错误的方式。
SIGNAL向处理程序,应用程序的外部或客户端提供错误信息。此外,它还提供对错误特征(错误编号,SQLSTATE
值,消息)的控制。如果没有SIGNAL,就必须采用变通方法,例如故意引用不存在的表来导致例程返回错误。
执行SIGNAL语句不需要特殊权限
。
要从诊断区域检索信息,请使用该
GET DIAGNOSTICS语句(请参见
第13.6.7.3节“GET DIAGNOSTICS语法”)。有关诊断区域的信息,请参见第13.6.7.7节“MySQL诊断区域”。
在condition_value一个
SIGNAL声明中表示要返回错误值。它可以是一个
SQLSTATE值(5个字符的字符串文字),或者condition_name是一个以前定义的命名条件
DECLARE ...
CONDITION(参见第13.6.7.1节“DECLARE ... CONDITION语法”)。
一个SQLSTATE值可以指示错误,警告或“ 未找到。“该值的前两个字符表示其错误类别,如
第13.6.7.5.1节”信号状态信息项目“中所述。一些信号值导致语句终止; 请参见
第13.6.7.5.2节“信号对处理程序,游标和语句的影响”。
语句
的SQLSTATE值
SIGNAL不应以'00'此类值开始,因为这些值表示成功,并且对于发出错误信号无效。无论SQLSTATE是在SIGNAL报表中直接指定值还是在报表中指定的命名条件中,都是如此。如果该值无效,Bad SQLSTATE则会发生错误。
用信号通知一个通用SQLSTATE值,
'45000'这意味着“ 未处理的用户定义的异常。”
该SIGNAL语句可以包含一个SET包含多个信号项的子句,用逗号分隔condition_information_item_name=
simple_value_specification
赋值列表
。
每个条款中condition_information_item_name
只能指定一次SET。否则,Duplicate condition information
item会发生错误。
simple_value_specification
可以使用存储过程或函数参数,用DECLARE用户定义变量,系统变量或文字声明的存储程序局部变量来指定
有效的指示符
。字符文字可能包括
_charset介绍人。
有关允许condition_information_item_name
值的信息
,请参见
第13.6.7.5.1节“信号状态信息项目”。
以下过程根据pval其输入参数的值指示错误或警告:
CREATE PROCEDURE p(pval INT)
开始
DECLARE专用条件SQLSTATE'45000';
IF pval = 0 THEN
SIGNAL SQLSTATE'01000';
ELSEIF pval = 1 THEN
SIGNAL SQLSTATE'45000'
SET MESSAGE_TEXT ='发生错误';
ELSEIF pval = 2 THEN
信号专业
SET MESSAGE_TEXT ='发生错误';
其他
SIGNAL SQLSTATE'01000'
SET MESSAGE_TEXT ='发生警告',MYSQL_ERRNO = 1000;
SIGNAL SQLSTATE'45000'
SET MESSAGE_TEXT ='发生错误',MYSQL_ERRNO = 1001;
万一;
结束;
如果pval为0,则p()发出警告,因为SQLSTATE开头的值是'01'警告级别中的信号。警告不会终止程序,并且可以SHOW WARNINGS在程序返回后看到。
如果pval是1,则p()发出错误信号并设置MESSAGE_TEXT条件信息项。该错误终止该过程,并且文本与错误信息一起返回。
如果pval是2,则会发出相同的错误,但SQLSTATE在此情况下,使用命名条件指定该值。
如果pval是其他内容,则
p()首先发出警告并设置消息文本和错误编号条件信息项。该警告不会终止该过程,因此执行继续,p()然后发出错误信号。该错误会终止该过程。由警告设置的消息文本和错误编号由错误所设置的值替换,错误信息返回错误信息。
SIGNAL通常在存储的程序中使用,但它是MySQL扩展,它允许在处理程序上下文之外。例如,如果您调用mysql客户端程序,则可以在提示符处输入以下任何语句:
mysql>SIGNAL SQLSTATE '77777';mysql>CREATE TRIGGER t_bi BEFORE INSERT ON t- >FOR EACH ROW SIGNAL SQLSTATE '77777';mysql>CREATE EVENT e ON SCHEDULE EVERY 1 SECOND- >DO SIGNAL SQLSTATE '77777';
SIGNAL 根据以下规则执行:
如果SIGNAL语句表示特定的SQLSTATE值,则该值用于表示指定的条件。例:
CREATE PROCEDURE p(divisor INT)
开始
IF除数= 0 THEN
SIGNAL SQLSTATE'22012';
万一;
结束;
如果SIGNAL语句使用命名条件,则必须在适用于该SIGNAL
语句的某个范围内声明条件,并且必须使用SQLSTATE值定义条件
,而不是MySQL错误号。例:
CREATE PROCEDURE p(divisor INT)
开始
DECLARE divide_by_zero CONDITION FOR SQLSTATE'22012';
IF除数= 0 THEN
SIGNAL divide_by_zero;
万一;
结束;
如果SIGNAL声明的范围中不存在指定的条件
,
Undefined CONDITION则会发生错误。
如果SIGNAL引用的是使用MySQL错误号而不是SQLSTATE值定义的命名条件,SIGNAL/RESIGNAL
can only use a CONDITION defined with SQLSTATE则会发生错误。以下语句会导致该错误,因为指定的条件与MySQL错误号关联:
声明no_such_table条件1051; 信号no_such_table;
如果具有给定名称的条件在不同范围内被多次声明,则应用具有本地范围最多的声明。考虑以下过程:
CREATE PROCEDURE p(divisor INT)
开始
DECLARE my_error CONDITION FOR SQLSTATE'45000';
IF除数= 0 THEN
开始
DECLARE my_error CONDITION FOR SQLSTATE'22012';
SIGNAL my_error;
结束;
万一;
SIGNAL my_error;
结束;
如果divisor是0,则SIGNAL执行第一条
语句。最内层的my_error条件声明适用于提升SQLSTATE
'22012'。
如果divisor不是0,则SIGNAL执行第二条
语句。最外层的my_error条件声明适用于提升SQLSTATE
'45000'。
有关条件发生时服务器如何选择处理程序的信息,请参见第13.6.7.6节“处理程序的作用域规则”。
异常处理程序中可以提出信号:
CREATE PROCEDURE p()
开始
DECLARE退出处理器以处理SQLEXCEPTION
开始
SIGNAL SQLSTATE VALUE'99999'
SET MESSAGE_TEXT ='发生错误';
结束;
DROP TABLE no_such_table;
结束;
CALL p()达到
DROP TABLE声明。没有表名no_such_table,所以错误处理程序被激活。错误处理程序销毁原始错误(“ 没有这样的表 ”),并发出新的错误
SQLSTATE '99999'消息An error occurred。
下表列出了可以在SIGNAL(或
RESIGNAL)语句中设置的诊断区域条件信息项目的名称
。所有项目都是标准SQL,除了MYSQL_ERRNO这是MySQL扩展。有关这些项目的更多信息,请参见第13.6.7.7节“MySQL诊断区域”。
项目名称定义 --------- ---------- CLASS_ORIGIN VARCHAR(64) SUBCLASS_ORIGIN VARCHAR(64) CONSTRAINT_CATALOG VARCHAR(64) CONSTRAINT_SCHEMA VARCHAR(64) CONSTRAINT_NAME VARCHAR(64) CATALOG_NAME VARCHAR(64) SCHEMA_NAME VARCHAR(64) TABLE_NAME VARCHAR(64) COLUMN_NAME VARCHAR(64) CURSOR_NAME VARCHAR(64) MESSAGE_TEXT VARCHAR(128) MYSQL_ERRNO SMALLINT UNSIGNED
字符项目的字符集是UTF-8。
NULL在SIGNAL
声明中
分配条件信息项是非法的。
一条SIGNAL语句总是SQLSTATE直接指定一个值,或者通过引用一个用SQLSTATE值定义的命名条件来间接指定一个值。值的前两个字符SQLSTATE是它的类,并且该类将确定条件信息项的默认值:
班级= '00'(成功)
非法。SQLSTATE以开头的值'00'表示成功并且对于无效SIGNAL。
Class = '01'(警告)
MESSAGE_TEXT ='未处理的用户定义警告条件';
MYSQL_ERRNO = ER_SIGNAL_WARN
Class = '02'(未找到)
MESSAGE_TEXT ='未处理的用户定义未找到条件';
MYSQL_ERRNO = ER_SIGNAL_NOT_FOUND
类> '02'(例外)
MESSAGE_TEXT ='未处理的用户定义的异常情况';
MYSQL_ERRNO = ER_SIGNAL_EXCEPTION
对于法律类别,其他条件信息项目设置如下:
CLASS_ORIGIN = SUBCLASS_ORIGIN =''; CONSTRAINT_CATALOG = CONSTRAINT_SCHEMA = CONSTRAINT_NAME =''; CATALOG_NAME = SCHEMA_NAME = TABLE_NAME = COLUMN_NAME =''; CURSOR_NAME ='';
SIGNAL执行
后可访问的错误值是
SQLSTATE由SIGNAL语句和
MESSAGE_TEXT和
MYSQL_ERRNO项目引发的
值
。这些值可从C API获得:
SQLSTATE 价值:打电话
mysql_sqlstate()
MYSQL_ERRNO 价值:打电话
mysql_errno()
MESSAGE_TEXT 价值:打电话
mysql_error()
在SQL中,来自SHOW
WARNINGS和的输出以及和
列中SHOW
ERRORS的MYSQL_ERRNO
和MESSAGE_TEXT值
。
CodeMessage
要从诊断区域检索信息,请使用该
GET DIAGNOSTICS语句(请参见
第13.6.7.3节“GET DIAGNOSTICS语法”)。有关诊断区域的信息,请参见第13.6.7.7节“MySQL诊断区域”。
取决于信号类别,信号对语句执行有不同的影响。该课程确定错误的严重程度。MySQL忽略sql_mode系统变量的值
; 特别是严格的SQL模式并不重要。MySQL也忽略了IGNORE:意图
SIGNAL是明确地引发用户生成的错误,所以信号永远不会被忽略。
在下面的描述中,“ 未处理 ”意味着没有用信号SQLSTATE
值定义
处理程序DECLARE ...
HANDLER。
班级= '00'(成功)
非法。SQLSTATE以开头的值'00'表示成功并且对于无效SIGNAL。
Class = '01'(警告)
warning_count系统变量
的值
上升。SHOW
WARNINGS显示信号。
SQLWARNING处理程序捕捉到信号。如果信号在函数中未处理,则语句不会结束。
Class = '02'(未找到)
NOT FOUND处理程序捕捉到信号。对游标没有影响。如果信号在函数中未处理,则语句结束。
类> '02'(例外)
SQLEXCEPTION处理程序捕捉到信号。如果信号在函数中未处理,则语句结束。
Class = '40'
作为普通的例外处理。
例:
mysql>delimiter //mysql>CREATE FUNCTION f () RETURNS INT- >BEGIN- >SIGNAL SQLSTATE '01234'; -- signal a warning- >RETURN 5;- >END//mysql>delimiter ;mysql>CREATE TABLE t (s1 INT);mysql>INSERT INTO t VALUES (f());
结果是包含5的行被插入到表中
t。发信号的警告可以用来查看SHOW WARNINGS。
存储的程序可以包括在程序内出现特定条件时调用的处理程序。每个处理程序的适用性取决于程序定义内的位置及其处理的条件或条件:
在
BEGIN ...
END块中声明的处理程序仅在该块中的处理程序声明之后的SQL语句的作用域内。如果处理程序本身提出了一个条件,它不能处理该条件,在该块中也不能声明任何其他处理程序。在以下示例中,处理程序H1和
H2在范围为通过发言中提出的条件stmt1和
stmt2。但无论是
H1也不H2在范围上,以在体内引发条件H1
或H2。
BEGIN - 外部块 为... ...说明退出处理程序; - 处理程序H1 为... ...说明退出处理程序; - 处理者H2stmt1;stmt2; 结束;
处理程序仅适用于声明它的程序段,并且不能在该程序段外发生的情况下激活。在以下示例中,处理程序
H1位于
stmt1内部块中,但不在stmt2外部块中:
BEGIN - 外部块
BEGIN - 内部块
为... ...说明退出处理程序; - 处理程序H1
stmt1;
结束;
stmt2;
结束;
处理程序可以是特定的或一般的。特定的处理程序是针对MySQL错误代码,SQLSTATE值或条件名称的。一般的处理程序是用于在一个状态SQLWARNING,
SQLEXCEPTION或NOT
FOUND类。条件特异性与条件优先级有关,如后面所述。
多个处理程序可以在不同的范围内进行声明并具有不同的特性。例如,外部块中可能存在特定的MySQL错误代码处理程序,而SQLWARNING内部块中可能存在常规
处理程序。或者可能有一个特定的MySQL错误代码的处理程序和SQLWARNING同一块中的常规类。
处理程序是否被激活不仅取决于其自身的范围和条件值,还取决于其他处理程序的存在。当存储的程序中发生条件时,服务器在当前范围(当前BEGIN ...
END块)中搜索适用的处理程序
。如果没有适用的处理程序,则搜索将继续向外,并在每个包含范围(块)的每个连续处理程序中处理。当服务器在给定范围内找到一个或多个适用的处理程序时,它会根据条件优先级在其中选择:
MySQL错误代码处理程序优先于
SQLSTATE值处理程序。
一个SQLSTATE值处理程序优先于一般SQLWARNING,
SQLEXCEPTION或NOT
FOUND处理程序。
一个SQLEXCEPTION处理程序优先于SQLWARNING处理程序。
有可能有几个适用的处理程序具有相同的优先级。例如,一条语句可能会生成具有不同错误代码的多个警告,其中每个警告都存在一个错误特定的处理程序。在这种情况下,服务器激活哪个处理程序的选择是非确定性的,并且可能会根据情况发生的情况而改变。
处理程序选择规则的一个含义是,如果多个适用的处理程序出现在不同的作用域中,则具有最多本地作用域的处理程序优先于外部作用域中的处理程序,即使那些针对更具体条件的处理程序也是如此。
如果在条件发生时没有适当的处理程序,则采取的操作取决于条件的类别:
以下示例演示了MySQL如何应用处理程序选择规则。
此过程包含两个处理程序,一个用于为尝试删除不存在的表而发生的特定
SQLSTATE值('42S02'),另一个用于常规SQLEXCEPTION类:
CREATE PROCEDURE p1()
开始
为SQLSTATE'42S02'声明CONTINUE HANDLER
SELECT'SQLSTATE处理程序已激活'AS msg;
声明SQLEXCEPTION的继续处理程序
SELECT'SQLEXCEPTION处理程序已激活'AS msg;
DROP TABLE test.t;
结束;
这两个处理程序在同一个块中声明并具有相同的范围。但是,SQLSTATE处理程序优先于SQLEXCEPTION处理程序,因此如果表t不存在,则
DROP TABLE语句会引发一个激活SQLSTATE
处理程序的条件:
MySQL的> CALL p1();
+ -------------------------------- +
| msg |
+ -------------------------------- +
| SQLSTATE处理程序已激活|
+ -------------------------------- +
该过程包含相同的两个处理程序。但这一次,DROP TABLE语句和SQLEXCEPTION处理程序与
处理程序相关的内部块SQLSTATE:
CREATE PROCEDURE p2()
BEGIN - 外部块
为SQLSTATE'42S02'声明CONTINUE HANDLER
SELECT'SQLSTATE处理程序已激活'AS msg;
BEGIN - 内部块
声明SQLEXCEPTION的继续处理程序
SELECT'SQLEXCEPTION处理程序已激活'AS msg;
DROP TABLE test.t; - 发生在内部块中
结束;
结束;
在这种情况下,对条件发生的地方更为本地的处理程序优先。该
SQLEXCEPTION处理器激活,即使它是不是更一般的SQLSTATE处理程序:
MySQL的> CALL p2();
+ ------------------------------------ +
| msg |
+ ------------------------------------ +
| SQLEXCEPTION处理程序已激活|
+ ------------------------------------ +
在此过程中,其中一个处理程序在DROP
TABLE语句范围内的块中声明:
CREATE PROCEDURE p3()
BEGIN - 外部块
声明SQLEXCEPTION的继续处理程序
SELECT'SQLEXCEPTION处理程序已激活'AS msg;
BEGIN - 内部块
为SQLSTATE'42S02'声明CONTINUE HANDLER
SELECT'SQLSTATE处理程序已激活'AS msg;
结束;
DROP TABLE test.t; - 发生在外部块内
结束;
只有SQLEXCEPTION处理程序适用,因为另一个不适用于以下情况引发的情况
DROP TABLE:
MySQL的> CALL p3();
+ ------------------------------------ +
| msg |
+ ------------------------------------ +
| SQLEXCEPTION处理程序已激活|
+ ------------------------------------ +
在这个过程中,这两个处理程序在DROP TABLE
语句范围内的一个块中声明:
CREATE PROCEDURE p4()
BEGIN - 外部块
BEGIN - 内部块
声明SQLEXCEPTION的继续处理程序
SELECT'SQLEXCEPTION处理程序已激活'AS msg;
为SQLSTATE'42S02'声明CONTINUE HANDLER
SELECT'SQLSTATE处理程序已激活'AS msg;
结束;
DROP TABLE test.t; - 发生在外部块内
结束;
这两个处理程序都不适用,因为它们不在范围内
DROP TABLE。声明提出的条件未处理,并终止该过程,出现错误:
MySQL的> CALL p4();
错误1051(42S02):未知表'test.t'
SQL语句生成填充诊断区域的诊断信息。标准SQL具有诊断区域堆栈,其中包含每个嵌套执行上下文的诊断区域。标准SQL还支持GET STACKED
DIAGNOSTICS在条件处理程序执行期间引用第二个诊断区域的语法。MySQL支持STACKEDMySQL 5.7 的关键字。在此之前,MySQL不支持STACKED; 有一个诊断区域包含来自最近声明的信息。
本节介绍MySQL中诊断区域的结构,MySQL识别的信息项目,语句如何清除和设置诊断区域,以及诊断区域如何从堆栈中弹出和弹出。
诊断区域包含两种信息:
声明信息,例如发生的条件数量或受影响的行数。
状态信息,如错误代码和消息。如果一个语句提出了多个条件,诊断区域的这个部分每个都有一个条件区域。如果语句没有提供任何条件,则诊断区域的这部分是空的。
对于产生三个条件的语句,诊断区域包含像这样的语句和条件信息:
声明信息:
行数
...其他声明信息项目...
条件区域列表:
条件1:
条件1的错误代码
条件1的错误消息
...其他条件信息项目...
条件2:
条件2的错误代码:
条件2的错误消息
...其他条件信息项目...
条件3:
条件3的错误代码
条件3的错误消息
...其他条件信息项目...
诊断区域包含语句和条件信息项目。数字项是整数。字符项目的字符集是UTF-8。没有项目可以
NULL。如果语句或条件项未由填充诊断区域的语句设置,则其值为0或空字符串,具体取决于项目数据类型。
诊断区域的声明信息部分包含以下项目:
NUMBER:一个整数,表示具有信息的条件区域的数量。
ROW_COUNT:一个整数,表示受该语句影响的行数。
ROW_COUNT与ROW_COUNT()函数具有相同的值
(请参见
第12.14节“信息函数”)。
诊断区域的条件信息部分包含每个条件的条件区域。条件区域的编号从1到NUMBER语句条件项目的值
。如果
NUMBER是0,则没有条件区域。
每个条件区域包含以下列表中的项目。所有项目都是标准SQL,除了
MYSQL_ERRNO这是MySQL扩展。这些定义适用于除信号之外(即通过a SIGNAL或
RESIGNAL语句)生成的条件。对于非信号条件,MySQL仅填充那些未描述为始终为空的条件项。稍后将描述信号对条件区域的影响。
CLASS_ORIGIN:包含RETURNED_SQLSTATE值的类的字符串。如果该RETURNED_SQLSTATE值以SQL标准文档ISO 9075-2(第24.1节,SQLSTATE)中定义的类值开始,
CLASS_ORIGIN则为'ISO
9075'。否则,
CLASS_ORIGIN是的
'MySQL'。
SUBCLASS_ORIGIN:包含RETURNED_SQLSTATE
值的子类的字符串。如果CLASS_ORIGIN是'ISO
9075'或是RETURNED_SQLSTATE
以'000',
SUBCLASS_ORIGIN是'ISO
9075'。否则,
SUBCLASS_ORIGIN是的
'MySQL'。
RETURNED_SQLSTATE:表示SQLSTATE条件值的字符串。
MESSAGE_TEXT:表示条件的错误消息的字符串。
MYSQL_ERRNO:表示条件的MySQL错误代码的整数。
CONSTRAINT_CATALOG,
CONSTRAINT_SCHEMA,
CONSTRAINT_NAME:字符串指示目录,架构,并将其命名为违反约束。他们总是空着的。
CATALOG_NAME,
SCHEMA_NAME,
TABLE_NAME,
COLUMN_NAME:字符串指示目录,架构,表和相关的状态栏。他们总是空着的。
CURSOR_NAME:表示光标名称的字符串。这总是空的。
对于RETURNED_SQLSTATE,
MESSAGE_TEXT以及
MYSQL_ERRNO特定的错误值,请参阅第B.3节,“服务器错误代码和信息”。
如果SIGNAL(或
RESIGNAL)语句填充诊断区域,则其SET子句可以分配给任何条件信息项,除了
RETURNED_SQLSTATE对于项目数据类型合法的任何值。SIGNAL
也设定了RETURNED_SQLSTATE价值,但不是直接在其SET条款中。这个价值来自SIGNAL声明的
SQLSTATE论点。
SIGNAL还设置了声明信息项目。它设置NUMBER为1.它将ROW_COUNT错误设置为-1,否则设置为0。
非诊断SQL语句自动填充诊断区域,其内容可以使用SIGNAL和
RESIGNAL语句显式设置
。可以检查诊断区域GET
DIAGNOSTICS以提取特定项目,或使用
SHOW WARNINGS或
SHOW ERRORS看情况或错误。
SQL语句按如下方式清除并设置诊断区域:
当服务器解析后开始执行语句时,它将清除诊断语句的诊断区域。(MySQL的5.7.2之前,服务器将清除该使用表未诊断报表诊断区)诊断语句不明确的诊断区(SHOW
WARNINGS,SHOW
ERRORS,GET
DIAGNOSTICS)。
如果语句提出了一个条件,则诊断区域将清除属于先前语句的条件。例外情况是由诊断区域引发
GET DIAGNOSTICS并
RESIGNAL添加到诊断区域而未清除的情况。
因此,即使一条语句在开始执行时通常不会清除诊断区域,但如果语句产生条件,它也会清除它。
以下示例显示了使用中的各种诊断区域语句的影响 SHOW
WARNINGS用于显示有关存储在那里的条件的信息。
这个 DROP TABLE语句清除诊断区域,并在发生这种情况时将其填充:
MySQL的>DROP TABLE IF EXISTS test.no_such_table;查询OK,0行受影响,1个警告(0.01秒) MySQL的>SHOW WARNINGS;+ ------- + ------ + ---------------------------------- - + | 级别| 代码| 留言| + ------- + ------ + ---------------------------------- - + | 注意| 1051 | 未知表'test.no_such_table'| + ------- + ------ + ---------------------------------- - + 一排(0.00秒)
这个
SET
语句会生成一个错误,因此它会清除并填充诊断区域:
MySQL的>SET @x = @@x;错误1193(HY000):未知的系统变量'x' MySQL的>SHOW WARNINGS;+ ------- + ------ + ----------------------------- + | 级别| 代码| 留言| + ------- + ------ + ----------------------------- + | 错误| 1193 | 未知的系统变量'x'| + ------- + ------ + ----------------------------- + 一排(0.00秒)
前面的
SET
陈述产生了一个单一的条件,所以1是此时唯一有效的条件编号GET
DIAGNOSTICS。以下语句使用条件编号2,该条件编号会生成警告,并将其添加到诊断区域而不清除它:
MySQL的>GET DIAGNOSTICS CONDITION 2 @p = MESSAGE_TEXT;查询确定,0行受影响,1个警告(0.00秒) MySQL的>SHOW WARNINGS;+ ------- + ------ + ------------------------------ + | 级别| 代码| 留言| + ------- + ------ + ------------------------------ + | 错误| 1193 | 未知的系统变量'xx'| | 错误| 1753 | 条件编号无效| + ------- + ------ + ------------------------------ + 设置2行(0.00秒)
现在诊断区域中有两个条件,所以相同的GET DIAGNOSTICS语句成功:
MySQL的>GET DIAGNOSTICS CONDITION 2 @p = MESSAGE_TEXT;查询OK,0行受影响(0.00秒) MySQL的>SELECT @p;+ -------------------------- + | @p | + -------------------------- + | 条件编号无效| + -------------------------- + 一排(0.01秒)
发生诊断区域堆栈推入时,第一个(当前)诊断区域将成为第二个(堆叠)诊断区域,并将创建一个新的当前诊断区域作为其副本。在下列情况下,诊断区域将被推入并弹出堆栈:
执行存储的程序
推送发生在程序执行之前,之后发生弹出。如果处理程序正在执行时存储的程序结束,则可能会有多个诊断区域弹出; 发生这种情况是由于处理程序中没有适当的处理程序或因处理程序引起的异常
RETURN。
存储程序执行过程中发生的任何警告或错误情况将被添加到当前的诊断区域,但触发器中只会添加错误。当存储的程序结束时,呼叫者在当前的diagonstics区域中查看这些条件。
在存储的程序中执行条件处理程序
当由于条件处理程序激活而发生推送时,堆栈的诊断区域是在推送之前存储的程序中当前的区域。新的当前诊断区域是处理程序当前的诊断区域。
GET
[CURRENT] DIAGNOSTICS和
GET
STACKED DIAGNOSTICS可以在处理程序中用于访问当前(处理程序)和堆栈(存储程序)诊断区域的内容。最初,它们返回相同的结果,但处理程序内执行的语句修改当前诊断区域,根据正常规则清除和设置其内容(请参阅第13.6.7.7.3节“诊断区的填充方式”)。堆栈的诊断区域不能被处理程序内执行的语句修改,除非
RESIGNAL。
如果处理程序成功执行,则会弹出当前(处理程序)诊断区域,堆栈(存储程序)诊断区域将再次成为当前诊断区域。处理程序执行期间添加到处理程序诊断区域的条件被添加到当前的诊断区域。
执行 RESIGNAL
该RESIGNAL语句传递在执行存储程序内的复合语句内的条件处理程序期间可用的错误条件信息。
RESIGNAL可能会在传递一些或全部信息之前更改部分或全部信息,修改诊断堆栈,如
第13.6.7.4节“RESIGNAL语法”中所述。
某些系统变量控制或与诊断区域的某些方面有关:
max_error_count控制诊断区域中的条件区域的数量。如果出现比这更多的条件,MySQL会默默丢弃超出条件的信息。(添加的条件RESIGNAL总是被添加,旧的条件被放弃以便腾出空间。)
warning_count表示发生的情况的数量。这包括错误,警告和注释。通常情况下,
NUMBER并且
warning_count是相同的。但是,随着产生的条件数量超过max_error_count,数值
warning_count继续上升,而
由于在诊断区域中未存储附加条件NUMBER,max_error_count因此仍然保持上限。
error_count表示发生的错误数量。该值包括
“ 未找到 ”和异常情况,但不包括警告和注释。就像
warning_count它的价值可以超过
max_error_count。
如果sql_notes系统变量设置为0,音符不会被存储并且不会增加warning_count。
示例:如果max_error_count
是10,则诊断区域最多可以包含10个条件区域。假设一个声明提出了20个条件,其中12个是错误的。在这种情况下,诊断区域包含前10个条件,
NUMBER10个,
warning_count20个,和
error_count 12个。
max_error_count在下次尝试修改诊断区域之前
,对值的更改
不起作用。如果诊断区域包含10个条件区域并
max_error_count设置为5,则诊断区域的大小或内容不会立即生效。
MySQL帐户信息存储在mysql数据库的表中
。这个数据库和访问控制系统在第5章MySQL服务器管理中进行了广泛的讨论
,您应该参阅其他详细信息。
一些MySQL版本引入了对授权表结构的更改以添加新的特权或功能。为了确保您可以利用任何新功能,请更新您的授权表,以便在升级MySQL时拥有当前结构。请参见第4.4.7节“ mysql_upgrade - 检查并升级MySQL表”。
当read_only启用系统变量时SUPER,除了任何其他所需的权限之外,帐户管理语句
还需要权限。这是因为他们修改了mysql数据库中的表。
ALTER USER [如果存在]
user[ auth_option] [,user[auth_option ]] ...
[需要{无| | tls_option[[AND] tls_option] ...}]
[WITH resource_option[ resource_option] ...]
[ password_option| lock_option] ...
改变用户[如果存在]
USER()由' auth_string' 识别
user:
(请参见第6.2.3节“指定帐户名称”)
auth_option:{
被'识别'auth_string '
| 用auth_plugin
| 标识 用auth_pluginBY' 识别auth_string '
| 与auth_plugin'hash_string ''
}
tls_option:{
SSL
| X509
| CIPHER'cipher '
| 发行人'issuer '
| 学科 'subject '
}
resource_option:{
MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONScount
}
password_option:{
密码EXPIRE
| PASSWORD EXPIRE DEFAULT
| 密码永远不会出现
| 密码EXPIRE INTERVAL NDAY
}
lock_option:{
帐户锁定
| 帐户解锁
}
该ALTER USER语句修改MySQL帐户。它可以为现有帐户修改身份验证,SSL / TLS,资源限制和密码管理属性,并启用帐户锁定和解锁。
要使用ALTER USER,您必须具有数据库的全局CREATE USER特权或UPDATE特权
mysql。当
read_only启用系统变量时,ALTER USER还需要SUPER特权。
默认情况下,如果您尝试修改不存在的用户,则会发生错误。如果IF EXISTS给出了该子句,则该语句为每个不存在的指定用户生成警告,而不是错误。
在某些情况下,ALTER
USER可能会记录在服务器日志中或客户端的历史文件中,例如
~/.mysql_history,这意味着明文密码可能被读取该信息的任何人阅读。有关服务器日志发生这种情况以及如何控制它的条件的信息,请参见第6.1.2.3节“密码和日志记录”。有关客户端日志记录的类似信息,请参见
第4.5.1.3节“mysql日志记录”。
该ALTER
USER声明有几个方面,在下列主题下描述:
对于每个受影响的帐户,ALTER
USER修改相应的
mysql.user表格行以反映在语句中指定的属性。未指定的属性保留其当前值。
示例1:更改帐户的密码并使其过期。因此,用户必须使用指定的密码进行连接,并在下一个连接处选择一个新密码:
ALTER USER'jeffrey'@'localhost'
被' new_password'密码认证;
示例2:修改一个帐户以使用
sha256_password验证插件和给定的密码。要求每180天选择一个新密码:
ALTER USER'jeffrey'@'localhost'
用sha256_password BY' new_password' 识别
密码EXPIRE INTERVAL 180天;
示例3:锁定或解锁帐户:
ALTER USER'jeffrey'@'localhost'ACCOUNT LOCK; ALTER USER'jeffrey'@'localhost'ACCOUNT UNLOCK;
示例4:要求帐户使用SSL进行连接,并建立每小时20个连接的限制:
ALTER USER'jeffrey'@'localhost' 使用MAX_CONNECTIONS_PER_HOUR 20请求SSL;
每个帐户名称使用第6.2.3节“指定帐户名称”中描述的格式
。帐户名称的主机名部分(如果省略)默认为'%'。也可以指定
CURRENT_USER或
CURRENT_USER()引用与当前会话关联的帐户。
仅限一种语法,该帐户可以使用以下USER()函数指定
:
ALTER USER USER()IDENTIFIED BY' auth_string';
此语法可以更改您自己的密码,而不需要直接命名您的帐户。
对于ALTER USER允许auth_option值遵循user值的
语法,auth_option通过指定帐户身份验证插件,凭据(例如密码)或两者来指示帐户如何进行身份验证。每个
auth_option值适用
只到一个名为的前一个帐户。
遵循user规范,该声明可能包含SSL / TLS选项,资源限制,密码管理和锁定属性。所有这些选项对声明都是全球性的,并适用于
所有指定账户。
示例:此语句更改两个帐户,指定一些每个帐户的属性和一些全局属性:
改变用户
'jeffrey'@'localhost'IDENTIFIED BY' new_password',
'珍妮' @ 'localhost' 的
使用MAX_USER_CONNECTIONS 2请求SSL;
auth_optionfollowing jeffrey(IDENTIFIED BY)后面
的值
仅适用于其之前的帐户,因此它仅更改密码jeffrey。因为
jeanne,没有每个帐户的值(因此保持密码不变)。其余属性全局适用于该语句。对于这两个帐户,需要连接才能使用SSL,并且每个帐户最多可以用于两个同时连接:
在没有特定类型的选择的情况下,该账户在这方面保持不变。例如,没有锁定选项,账户的锁定状态不会改变。
帐户名称后面可以跟随一个
auth_option验证选项,该选项指定帐户验证插件,凭证或两者:
auth_plugin命名认证插件。插件名称可以是带引号的字符串或不带引号的名称。插件名称存储在系统表的plugin列中
mysql.user。
对于auth_option不指定身份验证插件的语法,默认插件由default_authentication_plugin
系统变量的值指示
。有关每个插件的说明,请参见
第6.5.1节“认证插件”。
凭证存储在系统表的
authentication_string列中
mysql.user。An
或
value指定帐户凭证,可以是明文(未加密)字符串,也可以是与帐户关联的验证插件所需的格式的哈希值:
'auth_string''hash_string'
对于使用的语法,
字符串是明文,并传递给认证插件进行可能的散列。插件返回的结果存储在
列中。插件可以使用指定的值,在这种情况下不会发生散列。
'auth_string'authentication_string
对于使用的语法,
字符串被认为已经以认证插件所需的格式进行散列处理。如果插件的散列格式不合适,它将不可用,并且不会发生客户端连接的正确认证。
'hash_string'
ALTER USER允许这些
auth_option语法:
IDENTIFIED BY
'
auth_string'
将帐户认证插件设置为默认插件,将明文
值传递
给插件进行散列,并将结果存储在帐户行中。
'auth_string'mysql.user
IDENTIFIED WITH
auth_plugin
将帐户身份验证插件设置为
auth_plugin,将凭据清除为空字符串(凭据与旧身份验证插件相关联,而不是新身份验证插件),并将结果存储在
mysql.user帐户行中。
另外,密码被标记为过期。下次连接时用户必须选择一个新的。
IDENTIFIED WITH
auth_plugin BY
'auth_string'
将帐户身份验证插件设置为
auth_plugin,将明文
值传递
给插件进行散列,并将结果存储在帐户行中。
'auth_string'mysql.user
IDENTIFIED WITH
auth_plugin AS
'hash_string'
将帐户身份验证插件设置为
auth_plugin并将哈希
值存储
在帐户行中。假定该字符串已经按照插件所需的格式进行散列处理。
'hash_string'mysql.user
示例1:将密码指定为明文; 使用默认插件:
ALTER USER'jeffrey'@'localhost'
IDENTIFIED BY password';
示例2:指定验证插件以及明文密码值:
ALTER USER'jeffrey'@'localhost'
用mysql_native_password标识
BY' password';
示例3:指定验证插件以及哈希密码值:
ALTER USER'jeffrey'@'localhost'
用mysql_native_password标识
AS'* 6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';
有关设置密码和身份验证插件的其他信息,请参见 第6.3.6节“分配帐户密码”和 第6.3.9节“可插入身份验证”。
除了基于用户名和凭证的常规认证之外,MySQL还可以检查X509证书属性。有关在MySQL中使用SSL / TLS的背景信息,请参见第6.4节“使用加密连接”。
要为MySQL帐户指定SSL / TLS相关选项,请使用REQUIRE指定一个或多个tls_option值的
子句
。
REQUIRE选项
顺序无关紧要,但没有选项可以指定两次。该
AND关键字是可选之间
REQUIRE选择。
ALTER USER允许这些
tls_option值:
NONE
表示该帐户没有SSL或X509要求。如果用户名和密码有效,则不允许未加密的连接。如果客户端有适当的证书和密钥文件,则可以使用加密连接,客户可以选择。
改变用户'jeffrey'@'localhost'要求无;
客户端默认尝试建立安全连接。对于具有的客户端,REQUIRE
NONE如果无法建立安全连接,则连接尝试会回退到未加密的连接。为了要求加密连接,客户需要仅指定
--ssl-mode=REQUIRED
选项; 如果无法建立安全连接,则连接尝试失败。
SSL
告诉服务器只允许该帐户的加密连接。
ALTER USER'jeffrey'@'localhost'需要SSL;
客户端默认尝试建立安全连接。对于具有的帐户,REQUIRE
SSL如果无法建立安全连接,则连接尝试失败。
X509
要求客户出示有效证书,但确切的证书,发行人和主题无关紧要。唯一的要求是应该可以使用其中一个CA证书验证其签名。使用X509证书总是意味着加密,所以SSL在这种情况下该
选项是不必要的。
ALTER USER'jeffrey'@'localhost'需要X509;
对于账户REQUIRE X509,客户必须指定--ssl-key
和--ssl-cert选项进行连接。(建议但不要求--ssl-ca也是必需的,
以便服务器提供的公共证书可以被验证。)这也是正确的ISSUER
,SUBJECT因为这些
REQUIRE选项意味着需求X509。
ISSUER
'
issuer'
要求客户出示由CA颁发的有效X509证书
。如果客户端提供的证书有效但具有不同的颁发者,则服务器拒绝该连接。使用X509证书总是意味着加密,所以在这种情况下该
选项是不必要的。
'issuer'SSL
ALTER USER'jeffrey'@'localhost'
REQUIRE ISSUER'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/
O=MySQL/CN=CA/emailAddress=ca@example.com“;
因为ISSUER暗示了X509客户的要求,所以客户必须指定
--ssl-key和
--ssl-cert选择连接。(建议但不要求--ssl-ca也要求,
以便服务器提供的公共证书可以被验证。)
SUBJECT
'
subject'
要求客户出示包含该主题的有效X509证书subject。如果客户端提供的证书有效但具有不同的主题,则服务器会拒绝该连接。使用X509证书总是意味着加密,所以SSL在这种情况下该
选项是不必要的。
ALTER USER'jeffrey'@'localhost'
REQUIRE SUBJECT'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/
O = MySQL演示客户端证书/
CN=client/emailAddress=client@example.com“;
MySQL会对
值与证书中的值进行简单的字符串比较
,因此必须准确地给出lettercase和component order与证书中的值相同。
'subject'
因为SUBJECT暗示了X509客户的要求,所以客户必须指定--ssl-key和
--ssl-cert选择连接。(建议但不要求--ssl-ca也要求,
以便服务器提供的公共证书可以被验证。)
CIPHER
'
cipher'
需要特定的密码方法来加密连接。需要此选项以确保使用足够强度的密码和密钥长度。如果使用使用短加密密钥的旧算法,则加密可能很弱。
ALTER USER'jeffrey'@'localhost' 需要密码'EDH-RSA-DES-CBC3-SHA';
的SUBJECT,ISSUER和
CIPHER选项可以在组合中的
REQUIRE条款:
ALTER USER'jeffrey'@'localhost'
REQUIRE SUBJECT'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/
O = MySQL演示客户端证书/
CN=client/emailAddress=client@example.com”
和发行人'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/
O=MySQL/CN=CA/emailAddress=ca@example.com”
和密码'EDH-RSA-DES-CBC3-SHA';
如第6.3.5节“设置帐户资源限制”中所述,可以限制帐户使用服务器资源的限制。为此,请使用WITH指定一个或多个resource_option值的子句。
WITH选项
顺序并不重要,但如果给定资源限制多次指定,则最后一个实例优先。
ALTER USER允许这些
resource_option值:
MAX_QUERIES_PER_HOUR
,
,
countMAX_UPDATES_PER_HOUR
countMAX_CONNECTIONS_PER_HOUR
count
这些选项会限制在任何给定的一小时内允许此帐户允许多少个查询,更新和服务器连接。(从查询缓存中为其提供结果的查询不计入该MAX_QUERIES_PER_HOUR
限制。)如果count是
0(默认值),则表示该帐户没有限制。
MAX_USER_CONNECTIONS
count
限制帐户同时连接服务器的最大数量。非零值
count明确指定帐户的限制。如果
count是0
(缺省值),则服务器将根据max_user_connections
系统变量的全局值确定帐户的同时连接数
。如果
max_user_connections也是零,则帐户没有限制。
例:
ALTER USER'jeffrey'@'localhost' WITH MAX_QUERIES_PER_HOUR 500 MAX_UPDATES_PER_HOUR 100;
ALTER USER支持password_option密码过期管理的多个
值,可以手动过期帐户密码或建立密码过期策略。策略选项不会过期密码。相反,他们确定服务器如何根据帐户密码的年龄将自动过期应用于帐户。对于给定帐户,其密码年龄根据最近一次密码更改的日期和时间进行评估。
这些选项适用于使用MySQL内置身份验证插件(mysql_native_password或
caching_sha2_password)的帐户。对于使用对外部凭证系统执行验证的插件的帐户,密码到期也必须在外部处理。有关密码管理策略的信息,请参见第6.3.7节“密码管理”。
如果帐户密码手动过期或者认为密码年龄大于自动过期策略的允许使用期限,则客户端会话将以限制模式运行。在限制模式下,会话中执行的操作会导致错误,直到用户建立新的帐户密码。有关限制模式的信息,请参见 第6.3.8节“密码过期和沙箱模式”。
ALTER USER允许这些
password_option值:
PASSWORD EXPIRE
立即过期帐户密码。
更改用户'jeffrey'@'localhost'密码EXPIRE;
PASSWORD EXPIRE DEFAULT
根据default_password_lifetime
系统变量的指定设置帐户,以便应用全局过期策略
。
ALTER USER'jeffrey'@'localhost'密码EXPIRE DEFAULT;
PASSWORD EXPIRE NEVER
禁用该帐户的密码到期,以便其密码永不过期。
改变用户'jeffrey'@'localhost'密码永远不会出现;
PASSWORD EXPIRE INTERVAL
N DAY
将帐户密码生存期设置为
N天。此声明要求密码每180天更改一次:
ALTER USER'jeffrey'@'localhost'密码EXPIRE INTERVAL 180天;
如果指定了多个密码管理选项,则最后一个优先。
可以通过将密码设置为当前值来“ 重置 ”密码。作为一个良好的政策,最好选择一个不同的密码。
MySQL使用ACCOUNT LOCK和ACCOUNT
UNLOCK选项来支持帐户锁定和解锁
,这些选项指定帐户的锁定状态。有关更多讨论,请参见
第6.3.11节“用户帐户锁定”。
如果指定了多个帐户锁定选项,则最后一个优先。
CREATE USER [如果不存在]
user[ auth_option] [,user[ auth_option]] ...
[需要{无| | tls_option[[AND] tls_option] ...}]
[WITH resource_option[ resource_option] ...]
[ password_option| lock_option] ...
user:
(请参见第6.2.3节“指定帐户名称”)
auth_option:{
'auth_string ' 识别
| 用auth_plugin
| 标识 用auth_plugin'auth_string ' 识别
| 以auth_plugin'hash_string '' 识别
| 通过密码识别' hash_string'
}
tls_option:{
SSL
| X509
| CIPHER'cipher '
| 发行人'issuer '
| 主题'subject '
}
resource_option:{
MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONScount
}
password_option:{
密码EXPIRE
| PASSWORD EXPIRE DEFAULT
| 密码永远不会出现
| 密码EXPIRE INTERVAL NDAY
}
lock_option:{
帐户锁定
| 帐户解锁
}
该CREATE USER声明创建新的MySQL帐户。它可以为新帐户建立认证,SSL / TLS,资源限制和密码管理属性,并控制帐户最初是锁定还是解锁。
要使用CREATE USER,您必须具有全局CREATE USER特权或数据库的INSERT特权
mysql。当
read_only启用系统变量时,CREATE USER还需要SUPER特权。
如果您尝试创建已存在的帐户,则会发生错误。如果IF NOT EXISTS给出该子句,则该语句会为每个已存在的已命名帐户生成警告,而不是错误。
在某些情况下,CREATE
USER可能会记录在服务器日志中或客户端的历史文件中,例如
~/.mysql_history,这意味着明文密码可能被读取该信息的任何人阅读。有关服务器日志发生这种情况以及如何控制它的条件的信息,请参见第6.1.2.3节“密码和日志记录”。有关客户端日志记录的类似信息,请参见
第4.5.1.3节“mysql日志记录”。
该CREATE
USER声明有几个方面,在下列主题下描述:
对于每个帐户,CREATE USER
在mysql.user系统表中创建一个新行。账户行反映了在声明中指定的属性。未指定的属性设置为其默认值:
身份验证:由default_authentication_plugin
系统变量定义的身份验证插件
,以及空凭证
SSL / TLS: NONE
资源限制:无限制
密码管理: PASSWORD EXPIRE
DEFAULT
帐户锁定: ACCOUNT UNLOCK
首次创建的帐户没有特权。要分配权限,请使用该GRANT
语句。
示例1:创建一个使用默认身份验证插件和给定密码的帐户。将密码标记为已过期,以便用户必须在第一次连接到服务器时选择一个新密码:
CREATE USER'jeffrey'@'localhost'
被' new_password'密码认证;
示例2:创建一个使用sha256_password身份验证插件和给定密码的帐户
。要求每180天选择一个新密码:
CREATE USER'jeffrey'@'localhost'
用sha256_password BY' new_password' 识别
密码EXPIRE INTERVAL 180天;
每个帐户名称使用第6.2.3节“指定帐户名称”中描述的格式 。例如:
CREATE USER'jeffrey'@'localhost'IDENTIFIED BY' password';
帐户名称的主机名部分(如果省略)默认为'%'。
user为账户命名的
每个值可能后跟一个可选
auth_option值,指示账户如何认证。这些值可以指定帐户身份验证插件和凭据(例如,密码)。每个
auth_option值适用
只到一个名为的前一个帐户。
遵循user规范,该声明可能包含SSL / TLS选项,资源限制,密码管理和锁定属性。所有这些选项对声明都是全球性的,并适用于
所有指定账户。
示例:此语句创建两个帐户,指定一些每个帐户属性和一些全局属性:
创建用户
'jeffrey'@'localhost'IDENTIFIED WITH mysql_native_password
BY' new_password1',
'jeanne'@'localhost'用sha256_password标识
按' new_password2'
需要MAX_QUERIES_PER_HOUR X509 60
账户锁定;
每个auth_option值(IDENTIFIED WITH ... BY在这种情况下)仅适用于其之前的帐户,因此每个帐户都使用指定的认证插件和密码。其余属性全局适用于该语句。对于这两个帐户,连接必须使用有效的X509证书进行,每小时最多允许60个查询。这两个帐户最初都是锁定的,因此它们是占位符,并且只有在管理员解锁后才能使用。
帐户名称后面可以跟随一个
auth_option验证选项,该选项指定帐户验证插件,凭证或两者:
auth_plugin命名认证插件。插件名称可以是带引号的字符串或不带引号的名称。插件名称存储在系统表的plugin列中
mysql.user。
对于auth_option不指定身份验证插件的语法,默认插件由default_authentication_plugin
系统变量的值指示
。有关每个插件的说明,请参见
第6.5.1节“认证插件”。
凭证存储在系统表的
authentication_string列中
mysql.user。An
或
value指定帐户凭证,可以是明文(未加密)字符串,也可以是与帐户关联的验证插件所需的格式的哈希值:
'auth_string''hash_string'
对于使用的语法,
字符串是明文,并传递给认证插件进行可能的散列。插件返回的结果存储在
列中。插件可以使用指定的值,在这种情况下不会发生散列。
'auth_string'authentication_string
对于使用的语法,
字符串被认为已经以认证插件所需的格式进行散列处理。如果插件的散列格式不合适,它将不可用,并且不会发生客户端连接的正确认证。
'hash_string'
CREATE USER允许这些
auth_option语法:
IDENTIFIED BY
'
auth_string'
将帐户认证插件设置为默认插件,将明文
值传递
给插件进行散列,并将结果存储在帐户行中。
'auth_string'mysql.user
IDENTIFIED WITH
auth_plugin
将帐户身份验证插件设置为
auth_plugin,将凭据清除为空字符串,并将结果存储在mysql.user帐户行中。
IDENTIFIED WITH
auth_plugin BY
'auth_string'
将帐户身份验证插件设置为
auth_plugin,将明文
值传递
给插件进行散列,并将结果存储在帐户行中。
'auth_string'mysql.user
IDENTIFIED WITH
auth_plugin AS
'hash_string'
将帐户身份验证插件设置为
auth_plugin并将哈希
值存储
在帐户行中。假定该字符串已经按照插件所需的格式进行散列处理。
'hash_string'mysql.user
IDENTIFIED BY PASSWORD
'
hash_string'
将帐户身份验证插件设置为默认插件并将哈希
值存储
在帐户行中。假定该字符串已经按照插件所需的格式进行散列处理。
'hash_string'mysql.user
IDENTIFIED BY PASSWORD 语法已被弃用,并将在未来的MySQL版本中被删除。
示例1:将密码指定为明文; 使用默认插件:
CREATE USER'jeffrey'@'localhost'
IDENTIFIED BY password';
示例2:指定验证插件以及明文密码值:
CREATE USER'jeffrey'@'localhost'
用mysql_native_password IDENTIFIED BY' password';
在每种情况下,存储在帐户行中的密码值都是与帐户关联的验证插件散列后的明文值
。
'password'
有关设置密码和身份验证插件的其他信息,请参见 第6.3.6节“分配帐户密码”和 第6.3.9节“可插入身份验证”。
除了基于用户名和凭证的常规认证之外,MySQL还可以检查X509证书属性。有关在MySQL中使用SSL / TLS的背景信息,请参见第6.4节“使用加密连接”。
要为MySQL帐户指定SSL / TLS相关选项,请使用REQUIRE指定一个或多个tls_option值的
子句
。
REQUIRE选项
顺序无关紧要,但没有选项可以指定两次。该
AND关键字是可选之间
REQUIRE选择。
CREATE USER允许这些
tls_option值:
NONE
表示该帐户没有SSL或X509要求。如果用户名和密码有效,则不允许未加密的连接。如果客户端有适当的证书和密钥文件,则可以使用加密连接,客户可以选择。
CREATE USER'jeffrey'@'localhost'REQUIRE NONE;
客户端默认尝试建立安全连接。对于具有的客户端,REQUIRE
NONE如果无法建立安全连接,则连接尝试会回退到未加密的连接。为了要求加密连接,客户需要仅指定
--ssl-mode=REQUIRED
选项; 如果无法建立安全连接,则连接尝试失败。
NONE如果未REQUIRE指定与SSL相关的选项,则为默认值
。
SSL
告诉服务器只允许该帐户的加密连接。
CREATE USER'jeffrey'@'localhost'REQUIRE SSL;
客户端默认尝试建立安全连接。对于具有的帐户,REQUIRE
SSL如果无法建立安全连接,则连接尝试失败。
X509
要求客户出示有效证书,但确切的证书,发行人和主题无关紧要。唯一的要求是应该可以使用其中一个CA证书验证其签名。使用X509证书总是意味着加密,所以SSL在这种情况下该
选项是不必要的。
CREATE USER'jeffrey'@'localhost'REQUIRE X509;
对于账户REQUIRE X509,客户必须指定--ssl-key
和--ssl-cert选项进行连接。(建议但不要求--ssl-ca也是必需的,
以便服务器提供的公共证书可以被验证。)这也是正确的ISSUER
,SUBJECT因为这些
REQUIRE选项意味着需求X509。
ISSUER
'
issuer'
要求客户出示由CA颁发的有效X509证书
。如果客户端提供的证书有效但具有不同的颁发者,则服务器拒绝该连接。使用X509证书总是意味着加密,所以在这种情况下该
选项是不必要的。
'issuer'SSL
CREATE USER'jeffrey'@'localhost'
REQUIRE ISSUER'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/
O=MySQL/CN=CA/emailAddress=ca@example.com“;
因为ISSUER暗示了X509客户的要求,所以客户必须指定
--ssl-key和
--ssl-cert选择连接。(建议但不要求--ssl-ca也要求,
以便服务器提供的公共证书可以被验证。)
SUBJECT
'
subject'
要求客户出示包含该主题的有效X509证书subject。如果客户端提供的证书有效但具有不同的主题,则服务器会拒绝该连接。使用X509证书总是意味着加密,所以SSL在这种情况下该
选项是不必要的。
CREATE USER'jeffrey'@'localhost'
REQUIRE SUBJECT'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/
O = MySQL演示客户端证书/
CN=client/emailAddress=client@example.com“;
MySQL会对
值与证书中的值进行简单的字符串比较
,因此必须准确地给出lettercase和component order与证书中的值相同。
'subject'
因为SUBJECT暗示了X509客户的要求,所以客户必须指定--ssl-key和
--ssl-cert选择连接。(建议但不要求--ssl-ca也要求,
以便服务器提供的公共证书可以被验证。)
CIPHER
'
cipher'
需要特定的密码方法来加密连接。需要此选项以确保使用足够强度的密码和密钥长度。如果使用使用短加密密钥的旧算法,则加密可能很弱。
CREATE USER'jeffrey'@'localhost' 需要密码'EDH-RSA-DES-CBC3-SHA';
的SUBJECT,ISSUER和
CIPHER选项可以在组合中的
REQUIRE条款:
CREATE USER'jeffrey'@'localhost'
REQUIRE SUBJECT'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/
O = MySQL演示客户端证书/
CN=client/emailAddress=client@example.com”
和发行人'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/
O=MySQL/CN=CA/emailAddress=ca@example.com”
和密码'EDH-RSA-DES-CBC3-SHA';
如第6.3.5节“设置帐户资源限制”中所述,可以限制帐户使用服务器资源的限制。为此,请使用WITH指定一个或多个resource_option值的子句。
WITH选项
顺序并不重要,但如果给定资源限制多次指定,则最后一个实例优先。
CREATE USER允许这些
resource_option值:
MAX_QUERIES_PER_HOUR
,
,
countMAX_UPDATES_PER_HOUR
countMAX_CONNECTIONS_PER_HOUR
count
这些选项会限制在任何给定的一小时内允许此帐户允许多少个查询,更新和服务器连接。(从查询缓存中为其提供结果的查询不计入该MAX_QUERIES_PER_HOUR
限制。)如果count是
0(默认值),则表示该帐户没有限制。
MAX_USER_CONNECTIONS
count
限制帐户同时连接服务器的最大数量。非零值
count明确指定帐户的限制。如果
count是0
(缺省值),则服务器将根据max_user_connections
系统变量的全局值确定帐户的同时连接数
。如果
max_user_connections也是零,则帐户没有限制。
例:
CREATE USER'jeffrey'@'localhost' WITH MAX_QUERIES_PER_HOUR 500 MAX_UPDATES_PER_HOUR 100;
帐户密码有一个年龄,根据最近一次密码更改的日期和时间进行评估。
CREATE USER支持password_option密码过期管理的多个
值,可以手动过期帐户密码或建立密码过期策略。策略选项不会过期密码。相反,他们确定服务器如何根据帐户密码的年龄将自动过期应用于帐户。对于给定帐户,其密码年龄根据最近一次密码更改的日期和时间进行评估。
这些选项适用于使用MySQL内置身份验证插件(mysql_native_password或
caching_sha2_password)的帐户。对于使用对外部凭证系统执行验证的插件的帐户,密码到期也必须在外部处理。有关密码管理策略的信息,请参见第6.3.7节“密码管理”。
如果帐户密码手动过期或者认为密码年龄大于自动过期策略的允许使用期限,则客户端会话将以限制模式运行。在限制模式下,会话中执行的操作会导致错误,直到用户建立新的帐户密码。有关限制模式的信息,请参见 第6.3.8节“密码过期和沙箱模式”。
CREATE USER允许这些
password_option值:
PASSWORD EXPIRE
导致新帐户的密码被标记为过期。
创建用户'jeffrey'@'localhost'密码EXPIRE;
PASSWORD EXPIRE DEFAULT
根据default_password_lifetime
系统变量的指定设置帐户,以便应用全局过期策略
。
CREATE USER'jeffrey'@'localhost'PASSWORD EXPIRE DEFAULT;
PASSWORD EXPIRE NEVER
禁用该帐户的密码到期,以便其密码永不过期。
创建用户'jeffrey'@'localhost'密码永远不会出现;
PASSWORD EXPIRE INTERVAL
N DAY
将帐户密码生存期设置为
N天。此声明要求密码每180天更改一次:
创建用户'jeffrey'@'localhost'密码EXPIRE INTERVAL 180天;
如果指定了多个密码管理选项,则最后一个优先。
MySQL使用ACCOUNT LOCK和ACCOUNT
UNLOCK选项来支持帐户锁定和解锁
,这些选项指定帐户的锁定状态。有关更多讨论,请参见
第6.3.11节“用户帐户锁定”。
如果指定了多个帐户锁定选项,则最后一个优先。
DROP USER [如果存在]user[,user] ...
该DROP USER语句删除一个或多个MySQL帐户及其特权。它从所有授权表中删除帐户的权限行。
要使用DROP USER,您必须具有全局CREATE USER特权或数据库的DELETE特权
mysql。当
read_only启用系统变量时,DROP USER还需要SUPER特权。
如果您尝试删除不存在的帐户,则会发生错误。如果IF EXISTS给出了该子句,则该语句为每个不存在的指定用户生成警告,而不是错误。
每个帐户名称使用第6.2.3节“指定帐户名称”中描述的格式 。例如:
DROP USER'jeffrey'@'localhost';
帐户名称的主机名部分(如果省略)默认为
'%'。
DROP USER不会自动关闭任何打开的用户会话。相反,如果具有打开会话的用户被删除,则在该用户的会话关闭之前,该语句才会生效。会话关闭后,用户将被丢弃,并且该用户下次尝试登录时将失败。这是设计。
DROP USER不会自动删除或使其中的旧用户创建的数据库或对象失效。这包括存储的程序或视图,DEFINER属性将为其删除的用户命名。尝试访问这些对象可能会在定义者安全上下文中执行时产生错误。(有关安全上下文的信息,请参见
第23.6节“对存储的程序和视图的访问控制”。)
GRANT
priv_type[(column_list)]
[,priv_type[(column_list)]] ...
ON [ object_type] priv_level
TO user[ auth_option] [,user[ auth_option]] ...
[需要{无| | tls_option[[AND] tls_option] ...}]
[与{授予选项| resource_option} ...]
授予代理user
到user[,user] ...
[有赠送选项]
object_type:{
表
| 功能
| 程序
}
priv_level:{
*
| *。*
| db_name*。
| db_name.tbl_name
| tbl_name
| db_name。routine_name
}
user:
(请参见第6.2.3节“指定帐户名称”)
auth_option:{
'auth_string ' 识别
| 用auth_plugin
| 标识 用auth_plugin'auth_string ' 识别
| 以auth_plugin'hash_string '' 识别
| 通过密码识别' hash_string'
}
tls_option:{
SSL
| X509
| CIPHER' cipher'
| 发行人' issuer'
| 主题' subject'
}
resource_option:{
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONScount
}
该GRANT声明授予MySQL用户帐户的特权。该GRANT声明有几个方面,在下列主题下描述:
该GRANT声明授予MySQL用户帐户的特权。
要使用GRANT,您必须拥有该
GRANT OPTION权限,并且您必须拥有您授予的权限。当
read_only启用系统变量时,GRANT还需要SUPER特权。
该REVOKE声明与GRANT管理员关联并使其能够删除帐户权限。请参见
第13.7.1.6节“REVOKE语法”。
每个帐户名称使用第6.2.3节“指定帐户名称”中描述的格式 。例如:
GRANT ALL ON db1。* TO'jeffrey'@'localhost';
该帐户的主机名部分(如果省略)默认为
'%'。
通常情况下,数据库管理员首先使用
CREATE USER创建帐户并定义其非特权特征,例如其密码,是否使用安全连接,限制对服务器资源的访问,然后用于
GRANT定义其特权。
ALTER USER可能被用来改变现有账户的非特权特征。例如:
CREATE USER'jeffrey'@'localhost'IDENTIFIED BY' password';
GRANT ALL ON db1。* TO'jeffrey'@'localhost';
GRANT SELECT ON db2.invoice TO'jeffrey'@'localhost';
ALTER USER'jeffrey'@'localhost'WITH MAX_QUERIES_PER_HOUR 90;
此处显示的示例不包含任何IDENTIFIED
条款 假设您CREATE USER在创建帐户时创建密码
以避免创建不安全的帐户。
如果在GRANT语句中指定的帐户尚不存在,GRANT可以在稍后讨论NO_AUTO_CREATE_USERSQL模式的条件下创建该
帐户
。还可以使用它
GRANT来指定非特权帐户特征,例如它是否使用安全连接并限制对服务器资源的访问。
但是,GRANT从MySQL 5.7.6开始,不建议使用创建帐户或定义非特权特性。相反,使用CREATE USER或
执行这些任务ALTER USER。
从mysql程序中,
在成功执行时进行GRANT响应
Query OK, 0 rows affected。要确定操作产生的权限,请使用SHOW GRANTS。请参见
第13.7.5.21节“SHOW GRANTS语法”。
在某些情况下,
GRANT可能会记录在服务器日志中或客户端的历史文件中,例如
~/.mysql_history,这意味着明文密码可能被读取该信息的任何人阅读。有关服务器日志发生这种情况以及如何控制它的条件的信息,请参见第6.1.2.3节“密码和日志记录”。有关客户端日志记录的类似信息,请参见
第4.5.1.3节“mysql日志记录”。
GRANT支持长达60个字符的主机名称。用户名称最多可以包含32个字符。数据库,表,列和例程名称最多可以包含64个字符。
不要试图通过更改mysql.user
表来更改用户名的允许长度。这样做会导致不可预知的行为,甚至可能导致用户无法登录到MySQL服务器。mysql除非通过第4.4.7节“ mysql_upgrade - 检查和升级MySQL表”中描述的过程,否则不要以任何方式更改数据库
中表的结构。
GRANT
语句中的
一些对象会被引用,尽管在许多情况下引用是可选的:帐户,数据库,表,列和例程名称。例如,如果帐户名称中的某个值user_name或
某个
host_name值作为不带引号的标识符是合法的,则不需要引用该标识符。但是,必须使用引号来指定
user_name包含特殊字符(例如-)的host_name字符串,或包含特殊字符或通配符(如%)的
字符串
; 例如
'test-user'@'%.com'。分别引用用户名和主机名。
要指定引用的值:
引用数据库,表,列和例程名称作为标识符。
引用用户名和主机名作为标识符或字符串。
引用密码为字符串。
有关字符串引用和标识符引用的指导原则,请参见 第9.1.1节“字符串文字”和 第9.2节“模式对象名称”。
在_和%通配符在指定的数据库名称时被允许
GRANT,在数据库级别授予权限的语句。例如,这意味着要将一个_字符用作数据库名称的一部分,请\_在
GRANT语句中指定它,以防止用户访问与通配符模式匹配的其他数据库; 例如GRANT ... ON
`foo\_bar`.* TO ...。
下表总结了priv_type可以为GRANTand
REVOKE语句指定的可允许的
特权类型以及每个特权可以授予的级别。有关每个特权的更多信息,请参见
第6.2.1节“MySQL提供的特权”。
表13.6 GRANT和REVOKE的允许权限
| 特权 | 意义和可授予的级别 |
|---|---|
ALL [PRIVILEGES] |
授予除指定访问级别GRANT OPTION和
除外的所有权限
PROXY。 |
ALTER |
启用使用ALTER TABLE。级别:全局,数据库,表格。 |
ALTER ROUTINE |
使存储的例程可以被更改或删除。级别:全局,数据库,程序。 |
CREATE |
启用数据库和表创建。级别:全局,数据库,表格。 |
CREATE ROUTINE |
启用存储的例程创建。级别:全局,数据库。 |
CREATE TABLESPACE |
启用表空间和日志文件组以创建,更改或删除。级别:全球。 |
CREATE TEMPORARY TABLES |
启用使用CREATE
TEMPORARY TABLE。级别:全局,数据库。 |
CREATE USER |
允许使用CREATE USER,
DROP USER,
RENAME USER,和
REVOKE ALL
PRIVILEGES。级别:全球。 |
CREATE VIEW |
启用视图以创建或更改。级别:全局,数据库,表格。 |
DELETE |
启用使用DELETE。级别:全局,数据库,表格。 |
DROP |
启用要删除的数据库,表和视图。级别:全局,数据库,表格。 |
EVENT |
为Event Scheduler启用事件。级别:全局,数据库。 |
EXECUTE |
使用户能够执行存储的例程。级别:全局,数据库,表格。 |
FILE |
使用户能够使服务器读取或写入文件。级别:全球。 |
GRANT OPTION |
启用授予或从其他帐户中删除的权限。级别:全局,数据库,表,程序,代理。 |
INDEX |
启用索引创建或删除。级别:全局,数据库,表格。 |
INSERT |
启用使用INSERT。级别:全局,数据库,表格,列。 |
LOCK TABLES |
启用LOCK TABLES对您有SELECT
权限的表的使用。级别:全局,数据库。 |
PROCESS |
使用户能够看到所有进程SHOW
PROCESSLIST。级别:全球。 |
PROXY |
启用用户代理。级别:从用户到用户。 |
REFERENCES |
启用外键创建。级别:全局,数据库,表格,列。 |
RELOAD |
启用FLUSH操作。级别:全球。 |
REPLICATION CLIENT |
使用户能够询问主服务器或从服务器在哪里。级别:全球。 |
REPLICATION SLAVE |
启用复制从服务器以从主服务器读取二进制日志事件。级别:全球。 |
SELECT |
启用使用SELECT。级别:全局,数据库,表格,列。 |
SHOW DATABASES |
启用SHOW DATABASES以显示所有数据库。级别:全球。 |
SHOW VIEW |
启用使用SHOW CREATE VIEW。级别:全局,数据库,表格。 |
SHUTDOWN |
启用使用mysqladmin关闭。级别:全球。 |
SUPER |
能够使用如其他行政业务
CHANGE MASTER TO,
KILL,
PURGE BINARY LOGS,
SET
GLOBAL,和中mysqladmin调试命令。级别:全球。 |
TRIGGER |
启用触发器操作。级别:全局,数据库,表格。 |
UPDATE |
启用使用UPDATE。级别:全局,数据库,表格,列。 |
USAGE |
“ 没有权限 ”的同义词 |
触发器与表关联。要创建或删除触发器,您必须拥有TRIGGER表格的
特权,而不是触发器。
在GRANT声明中,
ALL
[PRIVILEGES]或PROXY
特权必须由自己来命名,并且不能与其他优惠指定一起。
ALL
[PRIVILEGES]代表除权限GRANT OPTION和
PROXY特权之外授予权限级别的所有可用
特权。
USAGE可以被指定为创建一个没有权限的用户,或者指定一个帐户的
REQUIRE或WITH子句而不更改其现有的权限。(但是,不建议使用GRANT定义非特权特性。
MySQL帐户信息存储在mysql数据库的表中
。有关更多详细信息,请参阅第6.2节“MySQL访问权限系统”,其中详细讨论了mysql数据库和访问控制系统。
如果授予表拥有包含混合大小写数据库或表名称并且lower_case_table_names系统变量设置为非零值的特权行
,
REVOKE则不能用于撤销这些特权。有必要直接操作授权表。(GRANT在lower_case_table_names设置时不会创建这样的行,但可能在设置该变量之前创建了这样的行
。)
权限可以在几个级别上授予,具体取决于该ON子句使用的语法。对于
REVOKE,相同的
ON语法指定要删除的权限。
对于全局,数据库,表和常规级别,
GRANT ALL
仅分配授予级别上存在的特权。例如,是一个数据库级别的语句,因此它不会授予任何全局唯一权限,例如。授予不分配或
特权。
GRANT ALL ON
db_name.*FILEALLGRANT OPTIONPROXY
该object_type子句(如果存在)应指定为TABLE,
FUNCTION或PROCEDURE
当下列对象是表,存储函数或存储过程时。
用户对数据库,表,列或例程拥有OR的特权是作为每个特权级别的帐户特权的逻辑加法形成的
。例如,如果用户具有全局SELECT特权,则不会因在数据库,表或列级别缺少特权而拒绝特权。特权检查程序的细节在
第6.2.5节“访问控制,第2阶段:请求验证”中介绍。
如果即使对一个用户使用表,列或例程权限,服务器也会检查所有用户的表,列和例程权限,这会降低MySQL的速度。同样,如果限制任何用户的查询,更新或连接的数量,服务器必须监视这些值。
MySQL使您可以授予不存在的数据库或表的权限。对于表格,授予的CREATE
特权必须包含特权。此行为是有意设计的,旨在使数据库管理员能够为将要在稍后创建的数据库或表准备用户帐户和权限。
删除数据库或表时,MySQL不会自动撤消任何权限。但是,如果删除例程,则为该例程授予的任何例程级特权都将被撤销。
语句中
的user值
GRANT表示该语句适用的MySQL帐户。为了适应从任意主机向用户授予权限,MySQL支持user在表单中指定值
。
'user_name'@'host_name'
您可以在主机名称中指定通配符。例如,
适用于域中的任何主机,并
适用于C类子网中的任何主机。
'user_name'@'%.example.com'user_nameexample.com'user_name'@'198.51.100.%'user_name198.51.100
简单的形式
是一个同义词
。
'user_name''user_name'@'%'
MySQL不支持用户名中的通配符。要引用匿名用户,请使用以下GRANT语句指定具有空用户名的帐户
:
GRANT ALL ON test。* TO''@'localhost'...;
在这种情况下,任何使用匿名用户的正确密码从本地主机连接的用户都将被允许访问,且具有与匿名用户帐户相关的权限。
有关帐户名称中的用户名和主机名值的更多信息,请参见第6.2.3节“指定帐户名称”。
如果您允许本地匿名用户连接到MySQL服务器,则还应该将权限授予所有本地用户
。否则,匿名用户帐户
在
当指定的用户试图从本地机器上登录到MySQL服务器使用的系统表。有关详细信息,请参见
第6.2.4节“访问控制,第1阶段:连接验证”。
'user_name'@'localhost'localhostmysql.user
要确定此问题是否适用于您,请执行以下查询,该查询列出了所有匿名用户:
SELECT主机,用户FROM mysql.user WHERE User ='';
为避免刚描述的问题,请使用以下语句删除本地匿名用户帐户:
DROP USER''@'localhost';
对于GRANT允许auth_option值遵循
user值的语法,
auth_option首先
IDENTIFIED是指定帐户身份验证插件,凭据(例如密码)或两者的认证方式。auth_option子句的语法与该
语句相同CREATE USER。有关细节,请参见第13.7.1.2节“创建用户语法”。
使用GRANT定义帐户认证特性不赞成的MySQL 5.7.6的。相反,使用CREATE
USER或建立或更改认证特征ALTER USER。这个GRANT功能将在未来的MySQL版本中被删除。
当IDENTIFIED存在并且拥有全局授权特权(GRANT
OPTION)时,即使该帐户存在并且已经有密码,指定的任何密码都将成为该帐户的新密码。没有IDENTIFIED,帐户密码保持不变。
全局特权是管理的或适用于给定服务器上的所有数据库。要分配全局特权,请使用以下
ON *.*语法:
让所有的*。*到'someuser'@'somehost'; GRANT SELECT,INSERT ON *。* TO'someuser'@'somehost';
的CREATE TABLESPACE,
CREATE USER,
FILE,
PROCESS,
RELOAD,
REPLICATION CLIENT,
REPLICATION SLAVE,
SHOW DATABASES,
SHUTDOWN,和
SUPER特权是行政的,只能在全球范围内授予。
其他特权可以授予全球或更具体的级别。
GRANT OPTION 在全球范围内授予任何全局特权适用于所有全局特权。
MySQL将全局权限存储在
mysql.user系统表中。
数据库特权适用于给定数据库中的所有对象。要分配数据库级别的权限,请使用语法:
ON
db_name.*
让所有人都在mydb。*到'someuser'@'somehost'; GRANT SELECT,INSERT ON mydb。* TO'someuser'@'somehost';
如果使用ON *语法(而不是
ON *.*),则会在数据库级别为默认数据库分配权限。如果没有默认数据库,则会发生错误。
的CREATE,
DROP,
EVENT,
GRANT OPTION,
LOCK TABLES,和
REFERENCES权限可以在数据库级别指定。表或例程特权也可以在数据库级别指定,在这种情况下,它们适用于数据库中的所有表或例程。
MySQL将数据库权限存储在
mysql.db系统表中。
表权限适用于给定表中的所有列。要分配表级权限,请使用语法:
ON
db_name.tbl_name
把所有的东西都放在mydb.mytbl上'someuser'@'somehost'; GRANT SELECT,插入mydb.mytbl TO'someuser'@'somehost';
如果您指定tbl_name而不是
db_name.tbl_name,则该语句适用tbl_name于默认数据库。如果没有默认数据库,则会发生错误。
容许priv_type在表级的值是ALTER,
CREATE VIEW,
CREATE,
DELETE,
DROP,
GRANT OPTION,
INDEX,
INSERT,
REFERENCES,
SELECT,
SHOW VIEW,
TRIGGER,和
UPDATE。
表级权限适用于基表和视图。CREATE
TEMPORARY TABLE即使表名匹配,它们也不适用于使用创建的表。有关TEMPORARY表权限的信息,请参见第13.1.18.3节“CREATE TEMPORARY TABLE Syntax”。
MySQL在表中存储表特权
mysql.tables_priv。
列权限适用于给定表中的单个列。在列级别授予的每个权限必须紧跟在括号内的一列或多列之后。
GRANT SELECT(col1),INSERT(col1,col2)ON mydb.mytbl TO'someuser'@'somehost';
可允许priv_type用于列(即,当你使用一个数值
column_list条款)是
INSERT,
REFERENCES,
SELECT,和
UPDATE。
MySQL将列权限存储在
mysql.columns_priv系统表中。
在ALTER ROUTINE,
CREATE ROUTINE,
EXECUTE,和
GRANT OPTION权限适用于存储例程(过程和函数)。他们可以在全球和数据库级授予。除此之外
CREATE ROUTINE,这些特权可以在例程级授予各个例程。
授予mydb。*到'someuser'@'somehost'的CREATE CREATE ROUTINE; 执行程序mydb.myproc TO'someuser'@'somehost';
可允许priv_type在常规水平值ALTER
ROUTINE,EXECUTE和
GRANT OPTION。
CREATE ROUTINE不是例程级别的权限,因为您必须在全局或数据库级别拥有创建例程的权限。
MySQL在mysql.procs_priv系统表中存储例程级特权
。
该PROXY特权使一个用户成为另一个用户的代理。代理用户模拟或获取代理用户的身份; 也就是说,它假定代理用户的特权。
GRANT PROXY ON'localuser'@'localhost'TO'externaluser'@'somehost';
当PROXY被授予时,它必须是在GRANT语句中命名的唯一特权
,REQUIRE不能给出该
子句,并且唯一允许的WITH选项是WITH
GRANT OPTION。
代理要求代理用户通过插件进行认证,该插件在代理用户连接时将代理用户的名称返回给服务器,并且代理用户具有代理用户的
PROXY特权。有关详细信息和示例,请参见第6.3.10节“代理用户”。
MySQL在mysql.proxies_priv系统表中存储代理权限
。
如果在GRANT
语句中指定的帐户不存在,则采取的操作取决于
NO_AUTO_CREATE_USERSQL模式:
如果NO_AUTO_CREATE_USER
未启用,则GRANT
创建该帐户。除非您使用非空密码,否则这是非常不安全的IDENTIFIED BY。
如果NO_AUTO_CREATE_USER
启用,则GRANT失败并且不会创建该帐户,除非您指定非空密码IDENTIFIED BY或使用命名验证插件IDENTIFIED
WITH。
如果该帐户已存在,IDENTIFIED
WITH则禁止该帐户,因为该帐户仅用于创建新帐户时使用。
除了基于用户名和凭证的常规认证之外,MySQL还可以检查X509证书属性。有关在MySQL中使用SSL的背景信息,请参见第6.4节“使用加密连接”。
可选REQUIRE子句为MySQL帐户指定与SSL相关的选项。语法与CREATE USER
语句相同。有关细节,请参见第13.7.1.2节“创建用户语法”。
使用GRANT定义帐户SSL特性弃用MySQL的5.7.6的。而是使用CREATE USER或
建立或更改SSL特征
ALTER USER。这个
GRANT功能将在未来的MySQL版本中被删除。
可选WITH条款用于这些目的:
使用户能够将权限授予其他用户
为用户指定资源限制
该WITH GRANT OPTION条款赋予用户在给定权限级别给予其他用户任何特权的能力。
要授予GRANT OPTION
帐户权限而不另外更改其权限,请执行以下操作:
授予使用*。*到'someuser'@'somehost'使用授予选项;
要小心你给予的GRANT
OPTION特权,因为具有不同权限的两个用户可能能够组合特权!
您不能授予其他用户您自己没有的权限; 该GRANT OPTION
特权使您只能分配您自己拥有的特权。
请注意,当您授予用户
GRANT OPTION特定权限级别的权限时,该用户拥有(或将来可能会授予)的任何权限也可以由该用户授予其他用户。假设您授予用户INSERT数据库的权限。如果您然后授予
SELECT数据库权限并指定WITH GRANT OPTION该用户不仅可以授予其他用户SELECT特权,还
可以授予其他用户
INSERT。如果你再授予
UPDATE权限的数据库用户,用户可以授予
INSERT,
SELECT和
UPDATE。
对于非管理员用户,您不应该授予
ALTER全局权限或mysql数据库权限。如果你这样做,用户可以尝试通过重命名表来颠覆权限系统!
有关与特定特权相关的安全风险的更多信息,请参见 第6.2.1节“MySQL提供的特权”。
如第6.3.5节“设置帐户资源限制”中所述,可以限制帐户使用服务器资源的限制。为此,请使用WITH指定一个或多个resource_option值的子句。未指定的限制保留其当前值。语法与CREATE
USER语句相同。有关细节,请参见
第13.7.1.2节“创建用户语法”。
使用GRANT定义帐户资源限制被弃用MySQL的5.7.6的。相反,使用CREATE USER或
建立或更改资源限制
ALTER USER。这个
GRANT功能将在未来的MySQL版本中被删除。
MySQL和标准SQL版本之间最大的区别GRANT是:
MySQL将权限与主机名和用户名的组合相关联,而不是仅与用户名相关联。
标准SQL不具有全局或数据库级特权,也不支持MySQL支持的所有特权类型。
MySQL不支持标准的SQL
UNDER特权。
标准SQL特权是以分层方式构建的。如果你删除了一个用户,那么用户被授予的所有特权都将被撤销。如果你使用MySQL,这也是如此DROP USER。请参见
第13.7.1.3节“DROP USER语法”。
在标准SQL中,当您删除一个表时,该表的所有特权都将被撤消。在标准SQL中,当您撤销特权时,基于该特权授予的所有特权也将被撤销。在MySQL中,权限可以用语句DROP USER或
REVOKE语句来删除。
在MySQL中,可以INSERT仅拥有表中某些列的
特权。在这种情况下,您仍然可以INSERT
在表上执行语句,前提是您只为那些您有权访问的列插入值
INSERT。如果未启用严格SQL模式,则省略的列将设置为其隐式默认值。在严格模式下,如果任何省略的列没有默认值,则该语句被拒绝。(标准SQL要求您具有INSERT所有列的
权限。)有关严格SQL模式和隐式默认值的信息,请参阅第5.1.8节“服务器SQL模式”和第11.7节“数据类型默认值”。
重命名用户old_userTOnew_user[,old_userTOnew_user] ...
该RENAME USER声明重命名现有的MySQL帐户。旧帐户不存在或新帐户已存在时发生错误。
要使用RENAME USER,您必须具有全局CREATE USER特权或数据库的UPDATE特权
mysql。当
read_only启用系统变量时,RENAME USER还需要SUPER特权。
每个帐户名称使用第6.2.3节“指定帐户名称”中描述的格式 。例如:
RENAME USER'jeffrey'@'localhost'TO'jeff'@'127.0.0.1';
帐户名称的主机名部分(如果省略)默认为
'%'。
RENAME USER使旧用户持有的权限成为新用户持有的权限。但是,
RENAME USER不会自动删除或使其中的旧用户创建的数据库或对象失效。这包括存储的程序或视图,其DEFINER属性将为旧用户命名。尝试访问这些对象如果在定义者安全上下文中执行,则可能会产生错误。(有关安全上下文的信息,请参见
第23.6节“对存储的程序和视图的访问控制”。)
特权更改将按照第6.2.6节 “特权更改生效时”中的说明生效 。
REVOKE
priv_type[(column_list)]
[,priv_type[(column_list)]] ...
ON [ object_type] priv_level
FROM user[,user] ...
REVOKE ALL [PRIVILEGES],授权选项
FROM user[,user] ...
REVOKE代理user
从user[,user] ...
该REVOKE声明使系统管理员可以撤消MySQL帐户的权限。
当read_only系统变量被启用,REVOKE
要求SUPER除了在下面的讨论中所描述的任何其他所需的特权特权。
每个帐户名称使用第6.2.3节“指定帐户名称”中描述的格式 。例如:
REVOKE INSERT ON *。* FROM'jeffrey'@'localhost';
帐户名称的主机名部分(如果省略)默认为
'%'。
有关在其权限仍然存在,容许水平的细节priv_type,
priv_level和
object_type值,以及指定用户名和密码的语法,请参阅第13.7.1.4,“GRANT和REVOKE语法”
要使用第一种REVOKE语法,您必须拥有该GRANT OPTION
特权,并且您必须具有要撤消的特权。
要撤销所有权限,请使用第二种语法,该语法会删除指定用户或用户的所有全局,数据库,表,列和例程权限:
REVOKE ALL PRIVILEGES,GRANT OPTION FROMuser[,user] ...
要使用此REVOKE语法,您必须具有全局CREATE USER
特权或数据库的UPDATE
特权mysql。
必须从中撤销权限的用户帐户必须存在。
REVOKE删除权限,但不会删除mysql.user表项。要完全删除用户帐户,请使用DROP
USER。请参见第13.7.1.3节“DROP USER语法”。
如果授予表拥有包含混合大小写数据库或表名称并且lower_case_table_names系统变量设置为非零值的特权行
,
REVOKE则不能用于撤销这些特权。有必要直接操作授权表。(GRANT在lower_case_table_names设置时不会创建这样的行,但可能在设置变量之前创建了这样的行
。)
当从mysql
程序成功执行时,REVOKE回应
Query OK, 0 rows affected。要确定操作后剩余的权限,请使用
SHOW GRANTS。请参见
第13.7.5.21节“SHOW GRANTS语法”。
SET PASSWORD [FORuser] =password_optionpassword_option:{ 'auth_string' | 密码('auth_string') }
该SET PASSWORD声明将密码分配给MySQL用户帐户。
表示明文(未加密)密码。
'auth_string'
SET PASSWORD
... =
PASSWORD('
语法从MySQL 5.7.6开始已被弃用,并且将在未来的MySQL版本中被删除。
auth_string')
SET PASSWORD
... = '
语法不被弃用,但它auth_string'ALTER
USER是帐户更改的首选语句,包括分配密码。例如:
ALTER USERuserIDENTIFIED BY'auth_string';
在某些情况下,SET
PASSWORD可能会记录在服务器日志中或客户端的历史文件中,例如
~/.mysql_history,这意味着明文密码可能被读取该信息的任何人阅读。有关服务器日志发生这种情况以及如何控制它的条件的信息,请参见第6.1.2.3节“密码和日志记录”。有关客户端日志记录的类似信息,请参见
第4.5.1.3节“mysql日志记录”。
SET PASSWORD可以使用或不使用FOR明确命名用户帐户的子句:
使用子句,该语句设置指定帐户的密码,该密码必须存在:
FOR
user
为'jeffrey'@'localhost'设置密码=' auth_string';
在没有子句的情况下,该语句为当前用户设置密码:
FOR
user
SET PASSWORD =' auth_string';
任何使用非匿名帐户连接到服务器的客户端都可以更改该帐户的密码。要查看服务器将您认证为哪个帐户,请调用该
CURRENT_USER()函数:
SELECT CURRENT_USER();
设置指定帐户的密码(使用
FOR子句)需要数据库的
UPDATE特权
mysql。为自己设置密码(对于不具有FOR子句的非匿名帐户
)不需要特殊权限。当read_only系统变量被启用,SET PASSWORD
要求SUPER除了所需的其他特权的特权。
如果
给出了一个条款,则帐户名称使用第6.2.3节“指定帐户名称”中描述的格式
。例如:
FOR user
为'bob'@'%.example.org'设置密码=' auth_string';
帐户名称的主机名部分(如果省略)默认为
'%'。
密码可以通过以下方式指定:
使用没有的字符串
PASSWORD()
为'jeffrey'@'localhost'设置密码=' password';
SET PASSWORD将字符串解释为明文字符串,将其传递给与帐户关联的验证插件,并将插件返回的结果存储在
mysql.user帐户行中。(这个插件有机会将这个值散列成它期望的加密格式,插件可以使用指定的值,在这种情况下不会发生散列。)
使用PASSWORD()函数(从MySQL 5.7.6开始不推荐)
为'jeffrey'@'localhost'设置密码= PASSWORD(' password');
该PASSWORD()参数是明文(未加密的)密码。
PASSWORD()散列密码并返回加密的密码字符串以存储在mysql.user帐户行中。
该PASSWORD()函数使用由old_passwords系统变量值的值确定的哈希方法对密码进行哈希处理
。请确保
old_passwords具有与帐户关联的身份验证插件预期的哈希方法相对应的值。例如,如果帐户使用该
mysql_native_password插件,则该
old_passwords值必须为0:
SET old_passwords = 0;
为'jeffrey'@'localhost'设置密码= PASSWORD(' password');
如果该old_passwords值与身份验证插件所需的值不同,则返回的哈希密码值
PASSWORD()将不会被插件使用,并且不会发生客户端连接的正确身份验证。
下表显示了对于每种密码散列方法,允许的值old_passwords以及哪些验证插件使用散列方法。
| 密码散列法 | old_passwords值 | 关联的身份验证插件 |
|---|---|---|
| MySQL 4.1本机散列 | 0 | mysql_native_password |
| SHA-256哈希 | 2 | sha256_password |
有关设置密码和身份验证插件的其他信息,请参见 第6.3.6节“分配帐户密码”和 第6.3.9节“可插入身份验证”。
ANALYZE [NO_WRITE_TO_BINLOG | 本地]
TABLE tbl_name[,tbl_name] ...
ANALYZE TABLE执行密钥分发分析并存储指定表格的分布。对于MyISAM表格,这种说法相当于使用myisamchk --analyze。
ANALYZE TABLE与之合作
InnoDB,NDB和
MyISAM表。它不适用于视图。
ANALYZE TABLE支持分区表,您可以使用ALTER TABLE ...
ANALYZE PARTITION分析一个或多个分区; 有关更多信息,请参阅第13.1.8节“ALTER TABLE语法”和
第22.3.4节“维护分区”。
在分析过程中,该表用一个读锁InnoDB和for锁定
MyISAM。
默认情况下,服务器将ANALYZE
TABLE语句写入二进制日志,以便它们复制到复制从服务器。要禁止日志记录,请指定可选NO_WRITE_TO_BINLOG关键字或其别名LOCAL。
ANALYZE TABLE 使用下表中显示的列返回结果集。
| 柱 | 值 |
|---|---|
Table |
表名 |
Op |
总是 analyze |
Msg_type |
status,error,
info,note,或
warning |
Msg_text |
一条信息性消息 |
如果自上次密钥分发分析以来该表未发生更改,则不会再次分析该表。
MySQL使用存储的密钥分配来决定连接的表连接顺序,而不是常量。另外,当决定查询中的特定表使用哪些索引时,可以使用密钥分发。
有关密钥分配分析如何工作的更多信息InnoDB,请参见
第14.6.12.1节“配置持久性优化器统计参数”和
第14.6.12.3节“估计InnoDB表的ANALYZE TABLE复杂度”。另请参见
第14.8.1.7节“InnoDB表限制”。特别是,如果
innodb_stats_persistent
系统变量已启用,则必须ANALYZE TABLE在将实质数据加载到InnoDB表中或为其创建新索引之后运行
。
要检查存储的密钥分配基数,请使用该
SHOW INDEX语句或
INFORMATION_SCHEMA.STATISTICS
表格。请参见第13.7.5.22节“SHOW INDEX语法”和
第24.23节“INFORMATION_SCHEMA统计表”。
CHECK TABLEtbl_name[,tbl_name] ... [option] ...option= { 升级 | 快 | 快速 | 中 | EXTENDED | CHANGED }
CHECK TABLE检查一个或多个表格是否存在错误。对于MyISAM表格,关键统计信息也会更新。CHECK
TABLE还可以检查问题的视图,例如视图定义中引用的表不再存在的表。
要检查一个表格,你必须有一些特权。
CHECK TABLE适用于
InnoDB,
MyISAM,
ARCHIVE,和
CSV表格。
在运行之前CHECK TABLE对
InnoDB表,请参见
检查表使用说明InnoDB表。
CHECK TABLE支持分区表,您可以使用它ALTER TABLE ...
CHECK PARTITION来检查一个或多个分区; 有关更多信息,请参见第13.1.8节“ALTER TABLE语法”和
第22.3.4节“维护分区”。
CHECK TABLE 忽略未编制索引的虚拟生成列。
CHECK TABLE 使用下表中显示的列返回结果集。
| 柱 | 值 |
|---|---|
Table |
表名 |
Op |
总是 check |
Msg_type |
status,error,
info,note,或
warning |
Msg_text |
一条信息性消息 |
该声明可能会为每个检查表产生许多行信息。最后一行具有Msg_type
的价值status和
Msg_text正常应该是
OK。对于一张MyISAM桌子,如果你没有得到OK或者Table is
already up to date,你通常应该对桌子进行维修。请参见第7.6节“MyISAM表维护和崩溃恢复”。
Table is already up to date意味着表格的存储引擎表示不需要检查表格。
该FOR UPGRADE选项检查命名表是否与当前版本的MySQL兼容。使用时FOR UPGRADE,服务器检查每个表以确定表创建后表中的任何数据类型或索引是否存在任何不兼容的更改。如果不是,则检查成功。否则,如果存在可能的不兼容性,服务器将对该表执行全面检查(可能需要一些时间)。如果完整检查成功,则服务器.frm使用当前MySQL版本号标记表的
文件。标记该.frm文件可以确保使用相同版本的服务器进一步检查表格将会很快。
由于数据类型的存储格式已更改或者其排序顺序已更改,因此可能会出现不兼容的情况。我们的目标是避免这些变化,但偶尔他们有必要纠正比发布之间不兼容更差的问题。
FOR UPGRADE 发现这些不兼容性:
MySQL 4.1和5.0之间的TEXT列
InnoDB和MyISAM表的
结束空间索引顺序已
更改。
新DECIMAL数据类型的存储方法
在MySQL 5.0.3和5.0.5之间更改。
如果您的表由不同于当前正在运行的MySQL服务器的不同版本创建,
FOR UPGRADE则表示该表具有.frm带有不兼容版本的文件。在这种情况下,返回的结果集
CHECK TABLE包含一个Msg_type值为
error和Msg_text
值为的行Table upgrade required. Please do
"REPAIR TABLE `
tbl_name`" to
fix it!
有时会对需要重建表索引的字符集或归类进行更改。有关这些更改的详细信息,请参见 第2.11.1.2节“影响升级到MySQL 5.7的更改”。有关重建表的信息,请参见 第2.11.3节“重建或修复表或索引”。
该YEAR(2)数据类型已被弃用,并且在MySQL 5.7.5中被删除。对于包含
YEAR(2)列的表,
CHECK TABLE建议
REPAIR TABLE将其转换YEAR(2)为
YEAR(4)。
从MySQL 5.7.2开始,维护触发器创建时间。如果针对具有触发器的表运行,
CHECK TABLE
... FOR UPGRADE则为MySQL 5.7.2之前创建的每个触发器显示此警告:
触发器db_name。tbl_name。trigger_name没有CREATED属性。
该警告仅供参考。触发器没有改变。
如MySQL的5.7.7,表格被报告为需要重建,如果它包含在预5.6.4格式老时间列(TIME,
DATETIME,和
TIMESTAMP列不为小数精度秒支持)和
avoid_temporal_upgrade
系统变量被禁用。这有助于
mysql_upgrade检测并升级包含旧时间列的表。如果
avoid_temporal_upgrade启用,则FOR UPGRADE忽略表中存在的旧时间列; 因此,
mysql_upgrade不会升级它们。
要检查包含这些时间列并需要重建的表,请avoid_temporal_upgrade
在执行前
禁用
CHECK TABLE
... FOR UPGRADE。
对使用非本地分区的表发出警告,因为在MySQL 5.7中不推荐使用非本地分区,并在MySQL 8.0中将其删除。请参阅第22章分区。
下表显示了可以给出的其他检查选项。这些选项传递给存储引擎,可能会使用或忽略它们。
| 类型 | 含义 |
|---|---|
QUICK |
不要扫描行来检查不正确的链接。适用于
InnoDB和MyISAM
表格和视图。 |
FAST |
只检查没有正确关闭的表格。忽略
InnoDB; 仅适用于
MyISAM表格和视图。 |
CHANGED |
只检查自上次检查后已更改或尚未正确关闭的表格。忽略
InnoDB; 仅适用于
MyISAM表格和视图。 |
MEDIUM |
扫描行以验证删除的链接是否有效。这也会计算行的密钥校验和,并使用计算出的密钥校验和对其进行验证。忽略
InnoDB; 仅适用于
MyISAM表格和视图。 |
EXTENDED |
对每行的所有密钥进行全键查找。这确保了表格100%一致,但需要很长时间。忽略InnoDB; 仅适用于
MyISAM表格和视图。 |
如果没有选项QUICK,
MEDIUM或EXTENDED指定,动态格式MyISAM表的默认检查类型
是MEDIUM。这与
在表上运行myisamchk --medium-check的tbl_name结果相同。缺省检查类型也适用
MEDIUM于静态格式
MyISAM表,除非
CHANGED或FAST已指定。在这种情况下,默认是
QUICK。行扫描被跳过
CHANGED,FAST因为行很少损坏。
您可以结合使用检查选项,如以下示例中那样快速检查表格以确定它是否已正确关闭:
CHECK TABLE test_table FAST QUICK;
如果CHECK TABLE发现与被标记为表上没有问题,
“ 损坏 ”或“ 不正确关闭 ”,CHECK TABLE
可以删除标记。
如果表损坏,则问题很可能在索引中,而不在数据部分中。所有上述检查类型都会彻底检查索引,因此应该找出大多数错误。
要检查您认为没有问题的表格,请不要使用检查选项或QUICK选项。后者应该在你急着使用时使用,并且可以承担QUICK在数据文件中没有发现错误的非常小的风险。(在大多数情况下,在正常使用情况下,MySQL应该在数据文件中发现任何错误,如果发生这种情况,表格会被标记为“ 损坏 ”,并且在修复之前不能使用。)
FAST并且CHANGED主要用于从脚本(例如,从cron执行)到定期检查表的脚本。在大多数情况下,FAST是优先考虑的CHANGED。(唯一不是首选的情况是当你怀疑你在MyISAM代码中发现错误时。)
EXTENDED只有在运行正常检查后才能使用,但当MySQL试图更新行或按键查找行时,仍然会从表中获取错误。如果正常检查成功,这是不太可能的。
使用CHECK
TABLE ... EXTENDED可能会影响查询优化器生成的执行计划。
报告的某些问题CHECK
TABLE无法自动更正:
Found row where the auto_increment column has the
value 0。
这意味着在表中
AUTO_INCREMENT索引列中包含值为0的行中有一行AUTO_INCREMENT(通过使用UPDATE语句将列明确设置为0,可以创建列为0
的行
)。
这本身并不是一个错误,但如果您决定转储表并将其还原或ALTER TABLE在表上执行操作,则可能会造成麻烦
。在这种情况下,AUTO_INCREMENT列会根据AUTO_INCREMENT列的规则更改值
,这可能会导致重复键错误等问题。
要摆脱警告,请执行
UPDATE语句以将列设置为除0之外的某个值。
以下说明适用于
InnoDB表格:
如果CHECK TABLE遇到损坏的页面,服务器将退出以防止错误传播(错误#10132)。如果损坏发生在辅助索引中,但表格数据可读,则运行
CHECK TABLE仍然可以导致服务器退出。
如果CHECK TABLE遇到聚集索引中的损坏DB_TRX_ID或
DB_ROLL_PTR字段,
CHECK TABLE可能导致
InnoDB访问无效的撤消日志记录,从而导致与
MVCC相关的服务器退出。
如果CHECK TABLE在InnoDB表或索引中遇到错误,它会报告错误,并且通常会标记索引并且有时会将该表标记为已损坏,从而阻止进一步使用索引或表。此类错误包括次级索引中的条目数不正确或链接不正确。
如果CHECK TABLE在二级索引中发现不正确的条目数量,它会报告错误但不会导致服务器退出或阻止访问该文件。
CHECK TABLE调查索引页面结构,然后调查每个键入口。它不会验证指向群集记录的键指针,也不会遵循BLOB
指针的路径。
当InnoDB表被存储在它自己的
.ibd
文件,第一个3
页所述的
.ibd文件包含标题信息,而不是表或索引数据。该
CHECK TABLE声明不检测仅影响标题数据的不一致。要验证InnoDB .ibd文件的全部内容
,请使用innochecksum命令。
CHECK TABLE在大型InnoDB表上
运行时,其他线程可能在CHECK
TABLE执行期间被阻塞。为避免超时,信号量等待阈值(600秒)会延长2小时(7200秒)以进行CHECK
TABLE操作。如果InnoDB
检测到信号量等待240秒或更长时间,它会开始将InnoDB监视器输出打印到错误日志中。如果锁定请求超出信号量等待阈值,则InnoDB中止该过程。为了完全避免信号量等待超时的可能性,请运行
CHECK TABLE
QUICK而不是CHECK
TABLE。
CHECK TABLEInnoDB SPATIAL
索引的功能包括R树有效性检查和检查,以确保R树的行数与聚簇索引相匹配。
CHECK TABLE支持虚拟生成列的二级索引InnoDB。
以下说明适用于
MyISAM表格:
CHECK TABLE更新MyISAM表格的关键统计信息。
如果CHECK TABLE输出没有返回,OK或者Table is
already up to date通常应该对表格进行修复。请参见
第7.6节“MyISAM表维护和崩溃恢复”。
如果没有CHECK TABLE
选项QUICK,
MEDIUM或EXTENDED
指定,动态格式MyISAM表的默认检查类型
是
MEDIUM。这与在表上运行myisamchk --medium-check的
tbl_name结果相同。缺省检查类型也适用
MEDIUM于静态格式
MyISAM表,除非
CHANGED或FAST已指定。在这种情况下,默认是
QUICK。行扫描被跳过
CHANGED,FAST
因为行很少损坏。
CHECKSUM TABLEtbl_name[,tbl_name] ... [QUICK | EXTENDED]
CHECKSUM TABLE报告
表格内容的校验和。您可以使用此语句验证在备份,回滚或其他旨在将数据恢复到已知状态的操作之前和之后内容相同。
该声明需要SELECT该表的
特权。
此声明不支持视图。如果您CHECKSUM TABLE针对某个视图运行
,则该Checksum值始终为
NULL,并且会返回警告。
对于不存在的表,CHECKSUM
TABLE返回NULL并生成警告。
在校验和运算表被锁定了读锁InnoDB和
MyISAM。
默认情况下,整个表被逐行读取并计算校验和。对于大型表格,这可能需要很长时间,因此您只会偶尔执行此操作。这个逐行计算就是你用这个EXTENDED子句得到的结果,以及除此之外的
InnoDB所有其他存储引擎MyISAM,以及
MyISAM不是用这个CHECKSUM=1子句创建的表
。
对于MyISAM使用该CHECKSUM=1子句创建的表
,
CHECKSUM TABLE或者
CHECKSUM TABLE
... QUICK返回可以非常快地返回的“ 实时 ”表校验和。如果表格不符合所有这些条件,则该QUICK方法返回NULL。该表QUICK
不支持该方法InnoDB。有关该子句的语法,
请参见第13.1.18节“CREATE TABLE语法”CHECKSUM。
校验和值取决于表格行格式。如果行格式更改,则校验和也会更改。例如,对于时间类型,如存储格式
TIME,
DATETIME以及
TIMESTAMP在MySQL 5.6之前的MySQL 5.6.5改变,因此,如果5.5表升级到MySQL 5.6,校验和的值可能会改变。
如果两个表的校验和不同,那么几乎可以肯定的是这些表在某种程度上是不同的。但是,由于使用的散列函数
CHECKSUM TABLE不能保证无冲突,所以两个不相同的表可能会产生相同的校验和。
OPTIMIZE [NO_WRITE_TO_BINLOG | 本地]
TABLE tbl_name[,tbl_name] ...
OPTIMIZE TABLE重新组织表数据和相关索引数据的物理存储,以减少访问表时的存储空间并提高I / O效率。对每个表进行的确切更改取决于该表使用的
存储引擎。
OPTIMIZE TABLE在这些情况下
使用,具体取决于表的类型:
在对InnoDB具有自己的.ibd文件的表
执行大量插入,更新或删除操作后,因为它是在innodb_file_per_table
启用该选项的情况下创建的
。表和索引被重新组织,磁盘空间可以被操作系统回收使用。
FULLTEXT
对作为InnoDB表中索引
一部分的列进行大量插入,更新或删除操作之后。首先设置配置选项
innodb_optimize_fulltext_only=1
。要将索引维护期保持在合理的时间,请设置
innodb_ft_num_word_optimize
选项以指定要在搜索索引中更新的词数,然后运行一系列OPTIMIZE
TABLE语句直到搜索索引完全更新。
删除的大部分后MyISAM
或ARCHIVE表,或者使许多变化为MyISAM或ARCHIVE
具有可变长度的行表(表具有
VARCHAR,
VARBINARY,
BLOB,或
TEXT列)。删除的行保留在链接列表中,随后的
INSERT操作将重用旧的行位置。您可以使用OPTIMIZE
TABLE回收未使用的空间并对数据文件进行碎片整理。对表进行大量更改后,此语句可能还会提高使用该表的语句的性能,有时还会显着提高。
OPTIMIZE TABLE工程
InnoDB,
MyISAM和
ARCHIVE表。
OPTIMIZE TABLE也支持内存NDB表的动态列
。它不适用于内存表的固定宽度列,也不适用于磁盘数据表。OPTIMIZE
NDB Cluster表上的性能可以通过使用来调整
--ndb_optimization_delay,这可以控制处理批次行之间等待的时间长度OPTIMIZE TABLE。有关更多信息,请参阅
在NDB群集7.3中解决的先前的NDB群集问题。
对于NDB簇表,OPTIMIZE
TABLE可以通过(例如)中断执行OPTIMIZE操作的SQL线程来中断。
默认情况下,OPTIMIZE TABLE也
不能使用任何其它存储引擎创建的表工作,并返回指示这种缺乏支持的结果。您可以OPTIMIZE
TABLE通过使用该
选项启动mysqld来为其他存储引擎工作
--skip-new。在这种情况下,OPTIMIZE
TABLE只是映射到ALTER
TABLE。
此声明不适用于视图。
OPTIMIZE TABLE分区表支持。有关在分区表和表分区中使用此语句的信息,请参见
第22.3.4节“维护分区”。
默认情况下,服务器将OPTIMIZE
TABLE语句写入二进制日志,以便它们复制到复制从服务器。要禁止日志记录,请指定可选NO_WRITE_TO_BINLOG关键字或其别名LOCAL。
OPTIMIZE TABLE 使用下表中显示的列返回结果集。
| 柱 | 值 |
|---|---|
Table |
表名 |
Op |
总是 optimize |
Msg_type |
status,error,
info,note,或
warning |
Msg_text |
一条信息性消息 |
OPTIMIZE TABLE表捕获和抛出从旧文件复制表统计信息到新创建的文件时发生的任何错误。例如。如果所有者的用户ID
.frm,.MYD或
.MYI文件是从的用户ID不同的mysqld过程,
OPTIMIZE TABLE除非生成一个“不能改变文件的所有权”错误
的mysqld由启动
root用户。
对于InnoDB表,
OPTIMIZE TABLE映射到
ALTER TABLE ...
FORCE,它将重建表以更新索引统计信息并释放聚簇索引中未使用的空间。OPTIMIZE
TABLE当你在一张InnoDB桌子上运行时,它
会显示在输出中,如下所示:
mysql> OPTIMIZE TABLE foo; + ---------- + ---------- + ---------- + ---------------- -------------------------------------------------- - + | 表| 操作| Msg_type | Msg_text | + ---------- + ---------- + ---------- + ---------------- -------------------------------------------------- - + | test.foo | 优化| 注意| 表不支持优化,而是重新创建+分析| | test.foo | 优化| 状态| 好的| + ---------- + ---------- + ---------- + ---------------- -------------------------------------------------- - +
OPTIMIZE TABLE对常规和分区表使用
在线DDLInnoDB,这减少了并发DML操作的停机时间。OPTIMIZE
TABLE在封面上触发并执行
的表重建ALTER TABLE ...
FORCE已完成。在操作的准备阶段和提交阶段只会短暂地执行排他表锁。在准备阶段,更新元数据并创建中间表。在提交阶段,提交表元数据更改。
OPTIMIZE TABLE 在下列条件下使用表格复制方法重建表格:
当old_alter_table
系统变量启用时。
当启用mysqld
--skip-new选项时。
OPTIMIZE TABLE包含索引的表
不支持使用
联机DDL。而是使用表格复制方法。
InnoDBFULLTEXT
InnoDB使用页面分配方法存储数据,并且不会像传统存储引擎(例如MyISAM)那样遭受碎片化
。在考虑是否运行优化时,请考虑服务器将要处理的事务的工作量:
预计会出现一定程度的碎片化。
InnoDB仅填充
93%的页面,为更新留出空间而不必拆分页面。
删除操作可能会留下空白,导致页面的填充量比预期的要少,这可能会使值得优化表格。
当有足够的空间可用时,对行的更新通常会重写同一页中的数据,具体取决于数据类型和行格式。请参见 第14.9.1.5节“InnoDB表的压缩工作方式”和 第14.11.1节“InnoDB行存储概述”。
随着时间的推移,高并发工作负载可能会在索引中留下空隙,InnoDB因为通过其MVCC机制保留了相同数据的多个版本
。请参见
第14.3节“InnoDB多版本控制”。
对于MyISAM表格,其
OPTIMIZE TABLE工作如下:
如果该表已删除或拆分行,请修复该表。
如果索引页面未被排序,请对它们进行排序。
如果表的统计信息不是最新的(并且通过对索引进行排序无法完成修复),请更新它们。
OPTIMIZE TABLE在线执行常规和分区InnoDB
表。否则,MySQL 会在OPTIMIZE
TABLE运行时锁定表。
OPTIMIZE TABLE不会对R-tree索引进行排序,例如POINT列上的空间索引
。(Bug#23578)
修复[NO_WRITE_TO_BINLOG | 本地]
TABLE tbl_name[,tbl_name] ...
[QUICK] [EXTENDED] [USE_FRM]
REPAIR TABLE 修复可能损坏的表格,仅限某些存储引擎。
虽然通常情况下REPAIR TABLE,如果发生灾难,您绝不应该跑步
,但这种说法很可能会从MyISAM表中找回所有数据。如果您的表经常被损坏,请尝试找出原因,以免使用REPAIR TABLE。请参见
第B.5.3.3节“如果MySQL保持崩溃应执行的操作”和
第15.2.4节“MyISAM表问题”。
REPAIR TABLE检查表以查看是否需要升级。如果是这样,它会按照与之相同的规则执行升级
CHECK TABLE ... FOR
UPGRADE。有关更多信息,请参见第13.7.2.2节“CHECK TABLE语法”。
在执行表格修复操作之前对表格进行备份; 在某些情况下,操作可能会导致数据丢失。可能的原因包括但不限于文件系统错误。请参阅 第7章,备份和恢复。
如果服务器在REPAIR
TABLE操作过程中崩溃,重新启动服务器后必须立即REPAIR TABLE为该表执行另一个
语句,然后再对其执行任何其他操作。在最坏的情况下,您可能会有一个新的干净的索引文件,但没有关于数据文件的信息,然后执行的下一个操作可能会覆盖数据文件。这是一种不太可能但可能的情况,它突出了首先进行备份的价值。
如果主服务器上的表损坏并且REPAIR TABLE在其上运行,则原始表的所有更改都
不会传播到从服务器。
REPAIR TABLE工程
MyISAM,
ARCHIVE和
CSV表。对于
MyISAM表格,它与myisamchk -
tbl_name默认情况下具有相同的效果。此声明不适用于视图。
REPAIR TABLE分区表支持。但是,该USE_FRM
选项不能用于分区表上的此语句。
您可以使用ALTER TABLE ... REPAIR
PARTITION修复一个或多个分区; 有关更多信息,请参见第13.1.8节“ALTER TABLE语法”和
第22.3.4节“维护分区”。
NO_WRITE_TO_BINLOG 要么
LOCAL
默认情况下,服务器将REPAIR
TABLE语句写入二进制日志,以便它们复制到复制从服务器。要禁止日志记录,请指定可选NO_WRITE_TO_BINLOG
关键字或其别名LOCAL。
QUICK
如果使用该QUICK选项,则
REPAIR TABLE尝试仅修复索引文件,而不修复数据文件。这种类型的修复就像myisamchk --recover --quick完成的那样。
EXTENDED
如果使用该EXTENDED选项,MySQL将逐行创建索引,而不是一次创建一个索引并进行排序。这种类型的修复就像myisamchk --safe-recover所做的那样。
USE_FRM
该USE_FRM选项可用于.MYI索引文件丢失或其标头已损坏的情况。该选项告诉MySQL不要信任.MYI
文件头中的信息,并使用.frm文件中的信息重新创建它
。这种修复不能用myisamchk完成。
仅当您无法使用常规
模式时才
使用该USE_FRM选项
。告诉服务器忽略该文件会使重要的表元数据存储在
修复过程不可用的位置,这会产生有害的后果:
REPAIR.MYI.MYI
当前AUTO_INCREMENT值丢失。
表中已删除记录的链接已丢失,这意味着已删除记录的可用空间此后将保持空闲状态。
的.MYI报头指示该表是否被压缩。如果服务器忽略此信息,则无法分辨表格是否被压缩,修复会导致表格内容的更改或丢失。这意味着
USE_FRM不应该与压缩表一起使用。无论如何,这不应该是必要的:压缩表是只读的,所以它们不应该被破坏。
如果您使用USE_FRM由不同于当前正在运行的MySQL服务器版本创建的表,
REPAIR TABLE则不会尝试修复表。在这种情况下,返回的结果集REPAIR
TABLE包含一个
Msg_type值为
error和
Msg_text值为的行Failed
repairing incompatible .FRM file。
如果USE_FRM使用,
REPAIR TABLE则不检查表以查看是否需要升级。
REPAIR TABLE 使用下表中显示的列返回结果集。
| 柱 | 值 |
|---|---|
Table |
表名 |
Op |
总是 repair |
Msg_type |
status,error,
info,note,或
warning |
Msg_text |
一条信息性消息 |
该REPAIR TABLE声明可能会为每个修复的表格生成许多行信息。最后一行的Msg_type值是
status,Msg_test
通常应该是OK。对于
MyISAM表格,如果你没有得到
OK,你应该尝试用myisamchk --safe-recover来修复它
。(REPAIR TABLE没有实现myisamchk的所有选项,通过myisamchk --safe-recover,你也可以使用REPAIR TABLE
不支持的选项,比如
--max-record-length。)
REPAIR TABLE表捕获并抛出从旧损坏文件复制表统计信息到新创建文件时发生的任何错误。例如。如果所有者的用户ID
.frm,.MYD或
.MYI文件是从的用户ID不同的mysqld过程,
REPAIR TABLE除非生成一个“不能改变文件的所有权”错误
的mysqld由启动
root用户。
REPAIR TABLE如果它包含5.6.4以前格式的旧时态列(和
不支持小数秒精度的列)并且
系统变量被禁用TIME,
则升级表。如果
启用,则忽略表中存在的旧时态列,但不升级它们。
DATETIMETIMESTAMPavoid_temporal_upgradeavoid_temporal_upgradeREPAIR TABLE
要升级包含这些时间列的表,请avoid_temporal_upgrade在执行前禁用
REPAIR TABLE。
您可以REPAIR
TABLE通过设置某些系统变量来提高性能。请参见第8.6.3节“优化修理表语句”。
创建[聚合]功能function_name返回{STRING | INTEGER | REAL | DECIMAL} SONAMEshared_library_name
用户定义的函数(UDF)是一种使用像本地(内置)MySQL函数(如ABS()or
)一样工作的新函数来扩展MySQL的方法CONCAT()。
function_name是应该在SQL语句中用来调用该函数的名称。该
RETURNS子句指示函数返回值的类型。DECIMAL
是之后的合法值RETURNS,但是当前
DECIMAL函数返回字符串值,应该像STRING
函数一样写入。
shared_library_name是包含实现函数的代码的共享库文件的基本名称。该文件必须位于插件目录中。该目录由plugin_dir系统变量的值给出
。有关更多信息,请参见第28.4.2.5节“UDF编译和安装”。
要创建一个函数,您必须具有数据库的
INSERT权限
mysql。这是必要的,因为
CREATE FUNCTION在mysql.func系统表中添加一行
记录函数的名称,类型和共享库名称。如果你没有这张表,你应该运行
mysql_upgrade命令来创建它。请参见
第4.4.7节“ mysql_upgrade - 检查并升级MySQL表”。
一个活动函数是一个已经加载CREATE FUNCTION并且没有被删除的函数
DROP FUNCTION。除非使用该
选项启动mysqld,否则每次启动服务器时都会重新加载所有活动函数--skip-grant-tables。在这种情况下,UDF初始化会被跳过并且UDF不可用。
有关编写用户定义函数的说明,请参见 第28.4.2节“添加新的用户定义函数”。为了使UDF机制起作用,函数必须用C或C ++(或其他可以使用C调用约定的语言)编写,您的操作系统必须支持动态加载,并且您必须动态(非静态地)编译 mysqld。
一个AGGREGATE函数的工作方式与本地MySQL聚合(摘要)函数(如SUMor
)完全相同
COUNT()。为了
AGGREGATE工作,你的
mysql.func表格必须包含一
type列。如果你的
mysql.func表没有这个列,你应该运行mysql_upgrade程序来创建它(参见第4.4.7节“ mysql_upgrade - 检查和升级MySQL表”)。
要升级与UDF关联的共享库,请发出
DROP FUNCTION语句,升级共享库,然后发出
CREATE FUNCTION语句。如果先升级共享库然后再使用
DROP FUNCTION,服务器可能会崩溃。
删除功能 function_name
该语句将删除名为的用户定义函数(UDF)
function_name。
要删除一个函数,您必须拥有数据库的
DELETE权限
mysql。这是因为
DROP FUNCTION从mysql.func记录该函数的名称,类型和共享库名称的系统表中删除一行。
要升级与UDF关联的共享库,请发出
DROP FUNCTION语句,升级共享库,然后发出
CREATE FUNCTION语句。如果先升级共享库然后再使用
DROP FUNCTION,服务器可能会崩溃。
DROP FUNCTION也用于删除存储的函数(参见第13.1.27节“DROP PROCEDURE和DROP FUNCTION语法”)。
安装插件plugin_nameSONAME'shared_library_name'
这条语句安装一个服务器插件。它需要系统表的
INSERT特权
mysql.plugin。
plugin_name是在库文件中包含的插件描述符结构中定义的插件的名称(请参见第28.2.4.2节“插件数据结构”)。插件名称不区分大小写。为了获得最大的兼容性,插件名称应限制为ASCII字母,数字和下划线,因为它们在C源文件,shell命令行,M4和Bourne shell脚本以及SQL环境中使用。
shared_library_name是包含插件代码的共享库的名称。该名称包括文件扩展名(例如,
libmyplugin.so,
libmyplugin.dll,或
libmyplugin.dylib)。
共享库必须位于插件目录(由plugin_dir系统变量命名的目录
)中。该库必须位于插件目录中,而不是在子目录中。默认情况下,
plugin_dir是plugin由pkglibdir配置变量命名的
目录下的目录,但可以通过设置plugin_dir服务器启动时的值来更改它
。例如,在一个my.cnf
文件中设置它的值:
的[mysqld]
PLUGIN_DIR =/path/to/plugin/directory
如果这个值plugin_dir是一个相对路径名,它就是相对于MySQL基目录(basedir系统变量的值
)。
INSTALL PLUGIN加载并初始化插件代码以使插件可供使用。通过执行初始化函数来初始化插件,该函数处理插件在可以使用之前必须执行的任何设置。当服务器关闭时,它会为加载的每个插件执行取消初始化功能,以便插件有机会执行任何最终清理。
INSTALL PLUGIN还通过向表中添加指示插件名称和库文件名称的行来注册该插件mysql.plugin。在服务器启动时,服务器加载并初始化mysql.plugin表中列出的任何插件。这意味着一个插件只安装
INSTALL PLUGIN一次,而不是每次服务器启动。如果使用该--skip-grant-tables选项启动服务器,则不会在启动时加载插件
。
一个插件库可以包含多个插件。对于要安装的每个人,请使用单独的INSTALL
PLUGIN语句。每个语句都会命名一个不同的插件,但它们都指定相同的库名称。
INSTALL PLUGIN导致服务器读取option(my.cnf)文件,就像在服务器启动时一样。这使得插件可以从这些文件中获取任何相关的选项。即使在加载插件之前(如果使用loose前缀),也可以将插件选项添加到选项文件中
。也可以卸载插件,编辑my.cnf并重新安装插件。通过这种方式重新启动插件可以在不重新启动服务器的情况下启用新的选项值。
有关在服务器启动时控制单个插件加载的选项,请参见第5.5.1节“安装和卸载插件”。如果您在--skip-grant-tables给定选项时(指示服务器不读取系统表)需要为单个服务器启动加载插件
,请使用该--plugin-load选项。请参见
第5.1.4节“服务器命令选项”。
要删除插件,请使用该UNINSTALL
PLUGIN语句。
有关插件加载的更多信息,请参见 第5.5.1节“安装和卸载插件”。
要查看安装了哪些插件,请使用该
SHOW PLUGINS语句或查询INFORMATION_SCHEMA.PLUGINS
表格。
如果您重新编译插件库并需要重新安装它,则可以使用以下任一方法:
使用UNINSTALL PLUGIN卸载所有插件库,安装在插件目录中的新插件的库文件,然后使用
INSTALL PLUGIN安装的所有插件库。此过程的优点是可以在不停止服务器的情况下使用它。但是,如果插件库包含很多插件,则必须发布很多INSTALL PLUGIN和
UNINSTALL PLUGIN语句。
停止服务器,在插件目录中安装新的插件库文件,然后重新启动服务器。
卸载插件 plugin_name
该语句删除已安装的服务器插件。它需要系统表的DELETE特权
mysql.plugin。
UNINSTALL PLUGIN是的补充INSTALL PLUGIN。
plugin_name必须是mysql.plugin
表中列出的某个插件的名称。服务器执行插件的反初始化函数,并从mysql.plugin表中删除该插件的行
,以便后续服务器重新启动时不会加载并初始化该插件。
UNINSTALL PLUGIN不会删除插件的共享库文件。
如果任何使用它的表已打开,则无法卸载插件。
删除插件会影响关联表的使用。例如,如果全文分析器插件与FULLTEXT表上的索引相关联,那么卸载该插件将使该表不可用。任何访问表的尝试都会导致错误。该表甚至无法打开,因此您不能删除使用该插件的索引。这意味着除非你不关心表格内容,否则卸载插件是值得关注的。如果您卸载的插件无意在稍后重新安装,并且您关心表内容,则应该使用mysqldump转储表并WITH PARSER从转储中删除该
子句
CREATE TABLE语句,以便以后可以重新加载表。如果您不关心表格,DROP TABLE即使与表格关联的任何插件丢失,也可以使用。
有关插件加载的更多信息,请参见 第5.5.1节“安装和卸载插件”。
该SET
语句有几种形式。对与特定服务器功能无关的表单的说明显示在本节的小节中:
SET
使您可以将值分配给影响服务器或客户端操作的变量。请参见第13.7.4.1节“变量赋值的SET语法”。
var_name =
value
SET CHARACTER SET并将
SET NAMES值分配给与服务器当前连接关联的字符集和归类变量。请参见
第13.7.4.2节“SET CHARACTER SET语法”和
第13.7.4.3节“SET NAMES语法”。
其他表格的描述出现在其他地方,与其他与他们帮助实施的能力相关的陈述分组:
SET PASSWORD分配帐户密码。请参见第13.7.1.7节“SET PASSWORD语法”。
SET
TRANSACTION ISOLATION LEVEL设置事务处理的隔离级别。请参见
第13.3.6节“SET TRANSACTION语法”。
SETvariable_assignment[,variable_assignment] ...variable_assignment:user_var_name=expr|param_name=expr|local_var_name=expr| [GLOBAL | SESSION]system_var_name=expr| [@@全球。| @@会话。| @@]system_var_name=expr
SET
变量赋值的语法使您可以将值分配给影响服务器或客户端操作的不同类型的变量:
系统变量。请参见
第5.1.5节“服务器系统变量”。系统变量也可以在服务器启动时设置,如
第5.1.6节“使用系统变量”中所述。(要
显示系统变量名称和值,请使用该SHOW
VARIABLES语句;请参见
第13.7.5.39节“SHOW VARIABLES语法”。)
用户定义的变量。请参见 第9.4节“用户定义的变量”。
存储过程和函数参数,以及存储的程序局部变量。请参见 第13.6.4节“存储程序中的变量”。
一个SET
是分配变量值的语句不写入二进制日志,因此在复制方案只会影响您在其上执行它的主机。要影响所有复制主机,请在每个主机上执行语句。
以下示例说明
SET
了设置变量的语法。他们使用
=
赋值运算符,但
:=
赋值运算符也被允许用于此目的。
一个用户变量被写为
,并被赋值为一个表达式值,如下所示:
@var_name
SET @var_name=expr;
例子:
SET @name = 43; SET @total_tax =(SELECT SUM(tax)FROM taxable_transactions);
在expr从简单的(文字值)的范围可以以更复杂的(由一个标量子查询返回的值)。
SET
适用于定义它们的存储对象上下文中的参数和局部变量。以下过程使用counter本地变量作为循环计数器:
CREATE PROCEDURE p()
开始
DECLARE计数器INT DEFAULT 0;
WHILE计数器<10 DO
- ... 做工作 ...
SET counter = counter + 1;
END WHILE;
结束;
许多系统变量都是动态的,可以在运行时通过使用SET
语句来更改
。有关列表,请参见
第5.1.6.2节“动态系统变量”。要更改系统变量
SET,请按名称引用它,可选地在前面加上一个修饰符:
要指出一个变量是一个全局变量,在其名称前面加上GLOBAL关键字或
@@global.限定符:
SET GLOBAL max_connections = 1000; SET @@ global.max_connections = 1000;
该SUPER特权是设置全局变量所必需的。
要指出变量是会话变量,请在其名称前面加上SESSION关键字或者@@session.或者@@
限定符:
SET SESSION sql_mode ='TRADITIONAL'; SET @@ session.sql_mode ='TRADITIONAL'; SET @@ sql_mode ='TRADITIONAL';
设置会话变量通常不需要特殊权限,但有例外情况需要
SUPER特权(如
sql_log_bin)。客户端可以更改自己的会话变量,但不能更改其他客户端的会话变量。
LOCAL并且@@local.是同义词SESSION和
@@session.。
如果不存在修饰符,则
SET
更改会话变量。
在这些情况下发生错误:
在设置仅具有会话值的变量时
使用SET
GLOBAL(或@@global.):
MySQL的> SET GLOBAL sql_log_bin = ON;
错误1231(42000):变量'sql_log_bin'不能
设置为'ON'的值
在设置仅具有全局值的变量时
省略GLOBAL(或
@@global.):
MySQL的> SET max_connections = 1000;
错误1229(HY000):变量'max_connections'是a
GLOBAL变量,并且应该使用SET GLOBAL进行设置
在设置仅具有全局值的变量时
使用SET
SESSION(或@@SESSION.):
MySQL的> SET SESSION max_connections = 1000;
错误1229(HY000):变量'max_connections'是a
GLOBAL变量,并且应该使用SET GLOBAL进行设置
前面的修饰符只适用于系统变量。尝试将它们应用于用户定义的变量,存储过程或函数参数或存储的程序局部变量时发生错误。
一个SET
语句可以包含多个变量赋值,用逗号分隔。该语句将值分配给用户定义的变量和系统变量:
SET @x = 1,SESSION sql_mode ='';
如果设置了多个系统变量,则语句中最近的
GLOBAL或SESSION修饰符用于未指定修饰符的后续赋值。
多变量赋值的例子:
SET GLOBAL sort_buffer_size = 1000000,SESSION sort_buffer_size = 1000000; SET @@ global.sort_buffer_size = 1000000,@@ local.sort_buffer_size = 1000000; SET GLOBAL max_connections = 1000,sort_buffer_size = 1000000;
如果语句中的任何变量赋值
SET
失败,则整个语句失败并且不会更改变量。
如果更改了会话系统变量,则该值将在会话中保持有效,直到您将变量更改为不同的值或会话结束。该更改对其他会话没有影响。
如果更改全局系统变量,则会将该值记住并用于新会话,直到将该变量更改为其他值或服务器退出。任何访问全局变量的客户端都可以看到该更改。但是,更改仅影响更改后连接的客户端的相应会话变量。全局变量更改不影响任何当前客户端会话的会话变量(甚至不包括SET
GLOBAL发生该语句的会话
)。
要使全局系统变量设置为永久性的,以便它适用于跨服务器重新启动,则还应将其设置为选项文件。
要将GLOBAL编译的MySQL默认值或SESSION变量的GLOBAL值设置为当前对应值,请将变量设置为该值DEFAULT。例如,以下两个语句在将会话值设置max_join_size为当前全局值时是相同的
:
SET @@ session.max_join_size = DEFAULT; SET @@ session.max_join_size = @@ global.max_join_size;
并非所有系统变量都可以设置为
DEFAULT。在这种情况下,将DEFAULT结果分配给
错误。
尝试分配
DEFAULT给用户定义的变量,存储过程或函数参数或存储的程序局部变量时发生错误。
要在表达式中引用系统变量的值,请使用其中一个@@-modifiers。例如,您可以SELECT
像这样在一个语句中检索值:
SELECT @@ global.sql_mode,@@ session.sql_mode,@@ sql_mode;
为了引用表达式中的系统变量
(而不是or
),MySQL会返回会话值(如果存在的话),否则返回全局值。这不同于
,它总是指会话值。
@@var_name@@global.@@session.SET @@var_name =
expr
SET {CHARACTER SET | CHARSET}
{' charset_name'| 默认}
该语句映射服务器和当前客户端之间发送的所有字符串。SET CHARACTER
SET设置三个会话系统变量:
character_set_client并
character_set_results设置给定的字符集,并设置
character_set_connection为的值
character_set_database。请参见
第10.4节“连接字符集和归类”。
charset_name 可能被引用或不引用。
默认的字符集映射可以通过使用该值来恢复DEFAULT。默认取决于服务器配置。
ucs2,utf16并且
utf32不能用作客户端字符集,这意味着它们不适用于SET
CHARACTER SET。
SET NAMES {' charset_name'
[COLLATE' collation_name'] | 默认}
该语句设置三届系统变量
character_set_client,
character_set_connection以及
character_set_results给定的字符集。设置
character_set_connection为
charset_name也设置
collation_connection为默认排序规则charset_name。请参见
第10.4节“连接字符集和归类”。
可选COLLATE子句可用于明确指定排序规则。如果给出,整理必须是允许的整理之一
charset_name。
charset_name并
collation_name可能被引用或未被引用。
默认映射可以通过使用值来恢复
DEFAULT。默认取决于服务器配置。
ucs2,utf16并且
utf32不能用作客户端字符集,这意味着它们不适用于
SET NAMES。
SHOW有许多形式提供有关服务器的数据库,表格,列或状态信息的信息。本节介绍以下内容:
SHOW {BINARY | MASTER}日志
SHOW BINLOG EVENTS [IN' log_name'] [FROM pos] [LIMIT [ offset,] row_count]
SHOW CHARACTER SET [ like_or_where]
SHOW COLLATION [ like_or_where]
SHOW [FULL] COLUMNS FROM tbl_name[FROM db_name] [ like_or_where]
SHOW CREATE DATABASE db_name
SHOW CREATE EVENT event_name
SHOW CREATE FUNCTION func_name
SHOW CREATE PROCEDURE proc_name
SHOW CREATE TABLE tbl_name
SHOW CREATE TRIGGER trigger_name
SHOW CREATE VIEW view_name
SHOW DATABASES [ like_or_where]
SHOW ENGINE engine_name{STATUS | MUTEX}
显示[存储]引擎
SHOW ERRORS [LIMIT [ offset,] row_count]
展示活动
SHOW FUNCTION CODE func_name
SHOW FUNCTION STATUS [ like_or_where]
SHOW GRANDS FOR user
SHOW INDEX FROM tbl_name[FROM db_name]
SHOW MASTER STATUS
SHOW OPEN TABLES [FROM db_name] [ like_or_where]
SHOW PLUGINS
SHOW PROCEDURE CODE proc_name
SHOW PROCEDURE STATUS [ like_or_where]
SHOW PRIVILEGES
SHOW [FULL] PROCESSLIST
SHOW PROFILE [ types] [FOR QUERY n] [OFFSET n] [LIMIT n]
SHOW PROFILES
SHOW RELAYLOG EVENTS [IN' log_name'] [FROM pos] [LIMIT [ offset,] row_count]
显示奴隶主
显示从属状态[用于通道channel]
SHOW [GLOBAL | SESSION]状态[ like_or_where]
SHOW TABLE STATUS [FROM db_name] [ like_or_where]
SHOW [FULL] TABLES [FROM db_name] [ like_or_where]
SHOW TRIGGERS [FROM db_name] [ like_or_where]
SHOW [GLOBAL | SESSION] VARIABLES [ like_or_where]
SHOW WARNINGS [LIMIT [ offset,] row_count]
like_or_where:
像' pattern''
| 哪里expr
如果给定SHOW
语句的语法包含一个部分,
则是一个可包含SQL 和
通配符的字符串。该模式对于将语句输出限制为匹配值很有用。
LIKE
'pattern''pattern'%_
几个SHOW语句也接受一个WHERE子句,该子句在指定显示哪些行时提供了更大的灵活性。请参见
第24.34节“SHOW语句的扩展”。
许多MySQL API(例如PHP)使您能够像处理来自某个SHOW语句的结果集一样处理从语句返回的结果
SELECT。有关更多信息,请参阅
第27章,连接器和API或您的API文档。另外,您可以使用SQL查询INFORMATION_SCHEMA数据库中表的查询结果
,但您无法轻松使用SHOW
语句结果。请参阅第24章INFORMATION_SCHEMA表。
SHOW BINARY LOGS SHOW MASTER LOGS
列出服务器上的二进制日志文件。此语句作为第13.4.1.1节“PURGE BINARY LOGS语法”中介绍的过程的一部分使用,该语句 显示如何确定可以清除哪些日志。
MySQL的> SHOW BINARY LOGS;
+ --------------- + ----------- +
| Log_name | File_size |
+ --------------- + ----------- +
| binlog.000015 | 724935 |
| binlog.000016 | 733481 |
+ --------------- + ----------- +
SHOW MASTER
LOGS相当于SHOW BINARY
LOGS。
具有SUPER或
REPLICATION CLIENT特权的用户可以执行此语句。
显示BINLOG事件 [IN'log_name'] [FROMpos] [LIMIT [offset,]row_count]
显示二进制日志中的事件。如果您未指定
,则会显示第一个二进制日志。
'log_name'
该LIMIT子句与语句的语法相同SELECT。请参见
第13.2.9节“SELECT语法”。
由于服务器向客户端返回二进制日志的完整内容(其中包括修改数据的服务器执行的所有语句),因此
发出不SHOW BINLOG EVENTS
带LIMIT子句的子句可能会耗费大量时间和资源。作为替代方案SHOW
BINLOG EVENTS,使用
mysqlbinlog实用程序将二进制日志保存到文本文件中供以后检查和分析。请参见
第4.6.7节“ mysqlbinlog - 处理二进制日志文件的实用程序”。
SHOW BINLOG EVENTS 显示二进制日志中每个事件的以下字段:
Log_name
正在列出的文件的名称。
Pos
事件发生的位置。
Event_type
描述事件类型的标识符。
Server_id
发生事件的服务器的服务器ID。
End_log_pos
下一个事件开始的位置,等于Pos事件的大小。
Info
有关事件类型的更多详细信息。这些信息的格式取决于事件类型。
某些与设置用户和系统变量有关的事件不包括在输出中
SHOW BINLOG EVENTS。要全面了解二进制日志中的事件,请使用
mysqlbinlog。
SHOW BINLOG EVENTS并
没有与中继日志文件。你可以SHOW RELAYLOG EVENTS用于这个目的。
SHOW CHARACTER SET
[LIKE' pattern'| WHERE expr]
该SHOW CHARACTER SET语句显示所有可用的字符集。该
LIKE子句(如果存在)指示要匹配哪些字符集名称。如第24.34节“对SHOW语句的扩展”中WHERE
所讨论的,可以使用该子句使用更一般的条件来选择行。例如:
MySQL的> SHOW CHARACTER SET LIKE 'latin%';
+ --------- + ----------------------------- + --------- ---------- + -------- +
| 字符集| 说明| 默认排序| Maxlen |
+ --------- + ----------------------------- + --------- ---------- + -------- +
| latin1 | cp1252西欧| latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2中欧| latin2_general_ci | 1 |
| latin5 | ISO 8859-9土耳其语| latin5_turkish_ci | 1 |
| latin7 | ISO 8859-13波罗的海| latin7_general_ci | 1 |
+ --------- + ----------------------------- + --------- ---------- + -------- +
该Maxlen列显示存储一个字符所需的最大字节数。
该filename字符集是仅供内部使用; 因此,SHOW CHARACTER
SET不显示它。
您还可以从中获取有关字符集的信息
INFORMATION_SCHEMA,其中包含一个
CHARACTER_SETS表。请参见
第24.1节“INFORMATION_SCHEMA CHARACTER_SETS表”。
SHOW COLLATION
[LIKE' pattern'| WHERE expr]
此语句列出服务器支持的排序规则。默认情况下,输出来自SHOW
COLLATION所有可用的排序规则。该
LIKE子句(如果存在)指示要匹配的排序规则名称。如第24.34节“对SHOW语句的扩展”中WHERE
所讨论的,可以使用该子句使用更一般的条件来选择行。例如:
MySQL的> SHOW COLLATION WHERE Charset = 'latin1';
+ ------------------- + --------- + ---- + --------- + ---- ------ + --------- +
| 整理| 字符集| Id | 默认| 编译| Sortlen |
+ ------------------- + --------- + ---- + --------- + ---- ------ + --------- +
| latin1_german1_ci | latin1 | 5 | | 是| 1 |
| latin1_swedish_ci | latin1 | 8 | 是| 是| 1 |
| latin1_danish_ci | latin1 | 15 | | 是| 1 |
| latin1_german2_ci | latin1 | 31 | | 是| 2 |
| latin1_bin | latin1 | 47 | | 是| 1 |
| latin1_general_ci | latin1 | 48 | | 是| 1 |
| latin1_general_cs | latin1 | 49 | | 是| 1 |
| latin1_spanish_ci | latin1 | 94 | | 是| 1 |
+ ------------------- + --------- + ---- + --------- + ---- ------ + --------- +
该Collation和Charset
列表示的整理和与它相关联的字符集的名称。Id是整理ID。Default指示排序规则是否是其字符集的默认值。
Compiled指示字符集是否被编译到服务器中。Sortlen与字符集中表示的字符串排序所需的内存量有关。
要查看每个字符集的默认排序规则,请使用以下语句。Default是一个保留字,因此要将其用作标识符,必须将其引用为:
MySQL的> SHOW COLLATION WHERE `Default` = 'Yes';
+ --------------------- + ---------- + ---- + --------- + - --------- --------- + +
| 整理| 字符集| Id | 默认| 编译| Sortlen |
+ --------------------- + ---------- + ---- + --------- + - --------- --------- + +
| big5_chinese_ci | big5 | 1 | 是| 是| 1 |
| dec8_swedish_ci | dec8 | 3 | 是| 是| 1 |
| cp850_general_ci | cp850 | 4 | 是| 是| 1 |
| hp8_english_ci | hp8 | 6 | 是| 是| 1 |
| koi8r_general_ci | koi8r | 7 | 是| 是| 1 |
| latin1_swedish_ci | latin1 | 8 | 是| 是| 1 |
...
您还可以从中获取有关排序规则的信息
INFORMATION_SCHEMA,其中包含一个
COLLATIONS表。参见
第24.2节“INFORMATION_SCHEMA COLLATIONS表”。
SHOW [FULL] {COLUMNS | FIELDS}
{FROM | IN} tbl_name
[{FROM | IN} db_name]
[LIKE' pattern'| WHERE expr]
SHOW COLUMNS显示关于给定表格中列的信息。它也适用于视图。
SHOW COLUMNS仅为那些您有某些特权的列显示信息。
您可以db_name.tbl_name用作语法的替代方法。换句话说,这两个陈述是等价的:
tbl_name
FROM db_name
显示列从mytable FROM mydb; 显示来自mydb.mytable的列;
可选FULL关键字使输出包含列整理和注释,以及您对每列的权限。
该LIKE子句(如果存在)指示要匹配哪些列名称。如第24.34节“对SHOW语句的扩展”中WHERE所讨论的,可以使用该
子句使用更一般的条件来选择行
。
MySQL的> SHOW COLUMNS FROM City;
+ ------------- + ---------- + ------ + ------ + --------- + - --------------- +
| 字段| 类型| 空| Key | 默认| 额外|
+ ------------- + ---------- + ------ + ------ + --------- + - --------------- +
| ID | int(11)| NO | PRI | NULL | auto_increment |
| 名称| char(35)| NO | | | |
| CountryCode | char(3)| NO | MUL | | |
| 区| char(20)| NO | | | |
| 人口| int(11)| NO | | 0 | |
+ ------------- + ---------- + ------ + ------ + --------- + - --------------- +
数据类型可能与您期望它们基于CREATE TABLE语句不同,因为当您创建或更改表时,MySQL有时会更改数据类型。发生这种情况的条件在第13.1.18.7节“无声柱规格变更”中有描述。
SHOW COLUMNS 为每个表列显示以下值:
Field
列名称。
Type
列数据类型。
Collation
非二进制字符串列或NULL其他列的排序规则
。仅当您使用FULL
关键字时,此值才会显示。
Null
列可空性。值是YES如果
NULL值可以存储在列中,
NO如果不存在。
Key
列是否被编入索引:
如果Key为空,则列不是索引的,或者仅作为多列非唯一索引中的次列索引。
如果Key是PRI,该列是一个PRIMARY KEY或多列中的一列PRIMARY
KEY。
如果Key是UNI,则该列是UNIQUE索引的第一列
。(一个
UNIQUE索引允许多个
NULL值,但您可以NULL通过检查该Null字段来判断该列是否允许。)
如果Key是MUL,则该列是列中允许出现多个给定值的非唯一索引的第一列。
如果超过一个Key值适用于表中给定的列,Key
显示了一个具有最高优先级,顺序
PRI,UNI,
MUL。
甲UNIQUE索引可被显示为
PRI,如果它不能包含
NULL值并没有
PRIMARY KEY在表中。甲
UNIQUE索引可能会显示为
MUL如果若干列形成复合
UNIQUE索引; 尽管列的组合是唯一的,但每列仍可以存在给定值的多次出现。
Default
列的默认值。这是
NULL如果列具有明确的默认值NULL,或者列定义不包含任何DEFAULT子句。
Extra
任何有关给定列的其他信息。在这些情况下,该值不是空的:
Privileges
您拥有专栏的权限。仅当您使用FULL
关键字时,此值才会显示。
Comment
列定义中包含的任何注释。仅当您使用FULL
关键字时,此值才会显示。
您还可以从中获取有关表格列的信息
INFORMATION_SCHEMA,其中包含一个
COLUMNS表格。请参见
第24.4节“INFORMATION_SCHEMA列表”。
您可以使用mysqlshow
db_name
tbl_name命令列出表格的列。
该DESCRIBE声明提供了类似于的信息SHOW
COLUMNS。请参见第13.8.1节“DESCRIBE语法”。
该SHOW CREATE TABLE,
SHOW TABLE STATUS和
SHOW INDEX声明还提供有关表格的信息。请参见第13.7.5节“SHOW语法”。
SHOW CREATE {DATABASE | SCHEMA} [如果不存在]db_name
显示CREATE DATABASE
创建指定数据库的语句。如果
SHOW声明包含一个IF NOT
EXISTS条款,则输出也包含这样一个条款。
SHOW
CREATE SCHEMA是一个同义词
SHOW CREATE DATABASE。
MySQL的>SHOW CREATE DATABASE test\G*************************** 1. row ******************** ******* 数据库:测试 创建数据库:CREATE DATABASE`test` / *!40100 DEFAULT CHARACTER SET latin1 * / MySQL的>SHOW CREATE SCHEMA test\G*************************** 1. row ******************** ******* 数据库:测试 创建数据库:CREATE DATABASE`test` / *!40100 DEFAULT CHARACTER SET latin1 * /
SHOW CREATE DATABASE根据sql_quote_show_create选项的值引用表名和列名
。请参见第5.1.5节“服务器系统变量”。
显示创建活动 event_name
此语句显示CREATE
EVENT重新创建给定事件所需的语句。它要求EVENT显示事件的数据库的特权。例如(使用第13.7.5.18节“SHOW EVENTS语法”中e_daily定义的相同事件并进行了更改):
mysql> SHOW CREATE EVENT test.e_daily \ G
*************************** 1. row ******************** *******
事件:e_daily
的sql_mode:
time_zone:SYSTEM
创建事件:CREATE EVENT`e_daily`
安排每天1天
启动CURRENT_TIMESTAMP +区间6小时
完成不存在
ENABLE
评论“然后保存会话总数
每天清理桌子'
DO BEGIN
INSERT INTO site_activity.totals(时间,总计)
SELECT CURRENT_TIMESTAMP,COUNT(*)
FROM site_activity.sessions;
DELETE FROM site_activity.sessions;
结束
character_set_client:latin1
collation_connection:latin1_swedish_ci
数据库整理:latin1_swedish_ci
character_set_client是character_set_client事件创建时系统变量的会话值。
collation_connection是collation_connection事件创建时系统变量的会话值。Database
Collation是与事件关联的数据库的排序规则。
输出反映了事件(ENABLE)的当前状态,而不是它创建的状态。
显示创建过程 proc_name
这个声明是一个MySQL扩展。它返回可用于重新创建指定存储过程的确切字符串。类似的语句SHOW CREATE
FUNCTION显示有关存储函数的信息(请参见第13.7.5.8节“SHOW CREATE FUNCTION语法”)。
要使用任一语句,您必须是在例程DEFINER子句中命名的用户,或者有权
SELECT访问
mysql.proc表。如果您对例程本身没有权限,则显示的Create Procedure或Create
Function字段的值
将为NULL。
MySQL的>SHOW CREATE PROCEDURE test.simpleproc\G*************************** 1. row ******************** ******* 过程:simpleproc 的sql_mode: 创建过程:CREATE PROCEDURE`simpleproc`(OUT param1 INT) 开始 SELECT COUNT(*)INTO param1 FROM t; 结束 character_set_client:latin1 collation_connection:latin1_swedish_ci 数据库整理:latin1_swedish_ci MySQL的>SHOW CREATE FUNCTION test.hello\G*************************** 1. row ******************** ******* 功能:你好 的sql_mode: 创建函数:CREATE FUNCTION`hello`(s CHAR(20)) 返回CHAR(50) 返回CONCAT('你好,',s,'!') character_set_client:latin1 collation_connection:latin1_swedish_ci 数据库整理:latin1_swedish_ci
character_set_client是character_set_client创建例程时系统变量的会话值。
collation_connection是collation_connection创建例程时系统变量的会话值。Database
Collation是与例程相关联的数据库的排序规则。
SHOW CREATE TABLE tbl_name
显示CREATE TABLE创建指定表的语句。要使用此语句,您必须拥有该表的某些特权。本声明也适用于观点。
MySQL的> SHOW CREATE TABLE t\G
*************************** 1. row ******************** *******
表:t
创建表:CREATE TABLE`t`(
`id` int(11)NOT NULL AUTO_INCREMENT,
``char(60)DEFAULT NULL,
PRIMARY KEY(`id`)
)ENGINE = InnoDB DEFAULT CHARSET = latin1
SHOW CREATE TABLE根据sql_quote_show_create选项的值引用表名和列名
。请参见第5.1.5节“服务器系统变量”。
有关CREATE
TABLEMySQL 如何存储语句的信息,请参见
第13.1.18.1节“CREATE TABLE语句保留”。
SHOW CREATE TRIGGER trigger_name
该语句显示CREATE
TRIGGER创建指定触发器的语句。该语句需要TRIGGER
与触发器关联的表的特权。
MySQL的> SHOW CREATE TRIGGER ins_sum\G
*************************** 1. row ******************** *******
触发器:ins_sum
sql_mode:STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
SQL原始语句:CREATE DEFINER =`me` @`localhost` TRIGGER ins_sum
插入帐户之前
FOR EACH ROW SET @sum = @sum + NEW.amount
character_set_client:utf8
collation_connection:utf8_general_ci
数据库整理:latin1_swedish_ci
创建于:2013-07-09 10:39:34.96
SHOW CREATE TRIGGER 输出具有以下列:
Trigger:触发器名称。
sql_mode:触发器执行时有效的SQL模式。
SQL Original Statement:CREATE TRIGGER定义触发器的
语句。
character_set_client:character_set_client
创建触发器时的系统变量的会话值。
collation_connection:collation_connection
创建触发器时的系统变量的会话值。
Database Collation:与触发器关联的数据库的归类。
Created:触发器创建的日期和时间。TIMESTAMP(2)对于在5.7.2或更高版本中NULL创建的触发器,对于5.7.2之前创建的触发器,这是一个
值(以百分之一秒为单位)。该列已添加到MySQL 5.7.2中。
您还可以从中获取有关触发器对象的信息
INFORMATION_SCHEMA,其中包含一个
TRIGGERS表。请参见
第24.28节“INFORMATION_SCHEMA触发器表”。
显示创建用户 user
此语句显示CREATE
USER创建指定用户的语句。如果用户不存在,则会发生错误。该声明需要数据库的
SELECT特权
mysql,除了显示当前用户的信息。
要为账户命名,请使用第6.2.3节“指定账户名称”中描述的格式
。帐户名称的主机名部分(如果省略)默认为'%'。也可以指定
CURRENT_USER或
CURRENT_USER()引用与当前会话关联的帐户。
MySQL的> SHOW CREATE USER 'root'@'localhost'\G
*************************** 1. row ******************** *******
CREATE USER for root @ localhost:CREATE USER'root'@'localhost'
用'mysql_native_password'识别
AS'* 2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19'
要求无密码入口默认帐户解锁
输出格式受log_builtin_as_identified_by_password
系统变量设置的影响
。
要显示授予帐户的权限,请使用该
SHOW GRANTS语句。请参见
第13.7.5.21节“SHOW GRANTS语法”。
显示创建视图 view_name
该语句显示CREATE
VIEW创建命名视图的语句。
MySQL的> SHOW CREATE VIEW v\G
*************************** 1. row ******************** *******
查看:v
创建视图:CREATE ALGORITHM = UNDEFINED
DEFINER =`bob` @`localhost`
SQL安全定义者视图
`v` AS选择1 AS`a`,2 AS``b`
character_set_client:latin1
collation_connection:latin1_swedish_ci
character_set_client是character_set_client视图创建时系统变量的会话值。
collation_connection是collation_connection视图创建时系统变量的会话值。
使用SHOW CREATE VIEW需要SHOW VIEW特权,以及有SELECT问题的视图的
特权。
您还可以从中获取有关视图对象的信息
INFORMATION_SCHEMA,其中包含一个
VIEWS表。请参见
第24.30节“INFORMATION_SCHEMA视图表”。
MySQL允许您使用不同的
sql_mode设置来告诉服务器要支持的SQL语法的类型。例如,您可以使用ANSISQL模式来确保MySQL正确解释查询中的标准SQL连接操作符doublebar(||)。如果您创建连接项目的视图,则可能会担心将sql_mode设置更改为
不同于其的值ANSI可能会导致视图无效。但这种情况并非如此。不管你如何写出一个视图定义,MySQL总是以规范的形式存储它。下面是一个示例,显示了服务器如何将双连接条连接操作符更改为CONCAT() 功能:
MySQL的>SET sql_mode = 'ANSI';查询OK,0行受影响(0.00秒) MySQL的>CREATE VIEW test.v AS SELECT 'a' || 'b' as col1;查询OK,0行受影响(0.01秒) MySQL的>SHOW CREATE VIEW test.v\G*************************** 1. row ******************** ******* 查看:v 创建视图:CREATE VIEW“v”AS select concat('a','b')AS“col1” ... 一排(0.00秒)
以规范形式存储视图定义的优点是稍后对值的更改
sql_mode不会影响视图的结果。然而,另一个后果是SELECT服务器从定义中剥离了之前的注释。
SHOW {DATABASES | SCHEMAS}
[LIKE' pattern'| WHERE expr]
SHOW DATABASES列出MySQL服务器主机上的数据库。
SHOW
SCHEMAS是一个同义词SHOW
DATABASES。该LIKE
子句(如果存在)指示要匹配哪些数据库名称。如第24.34节“对SHOW语句的扩展”中WHERE所讨论的,可以使用该
子句使用更一般的条件来选择行
。
您只会看到那些您拥有某种特权的数据库,除非您拥有全局SHOW
DATABASES特权。你也可以使用mysqlshow命令获得这个列表。
如果服务器是使用该--skip-show-database选项启动的,则
除非拥有该SHOW DATABASES权限,否则不能使用此语句
。
MySQL将数据库实现为数据目录中的目录,因此此语句仅列出该位置中的目录。但是,输出可能包含与实际数据库不对应的目录名称。
SHOW ENGINE engine_name{STATUS | MUTEX}
SHOW ENGINE显示关于存储引擎的操作信息。它需要
PROCESS特权。声明有这些变体:
显示引擎INNODB状态 SHOW ENGINE INNODB MUTEX SHOW ENGINE PERFORMANCE_SCHEMA STATUS
SHOW ENGINE INNODB
STATUS显示标准InnoDBMonitor关于InnoDB存储引擎状态的大量信息。有关InnoDB
提供InnoDB处理信息的标准监视器和其他监视器的信息
,请参见
第14.17节“InnoDB监视器”。
SHOW ENGINE INNODB
MUTEX显示InnoDB
互斥锁和
rw锁定统计信息。
InnoDB互斥锁和rwlocks也可以使用性能模式表进行监控。请参见
第14.16.2节“使用性能架构监控InnoDB互斥等待”。
SHOW ENGINE INNODB
MUTEX输出在MySQL 5.7.2中被删除。它被修改并重新在MySQL 5.7.8中引入。
在MySQL 5.7.8中,使用以下选项动态配置互斥量统计信息收集:
要启用互斥量统计信息的收集,请运行:
SET GLOBAL innodb_monitor_enable ='latch';
要重置互斥统计信息,请运行:
SET GLOBAL innodb_monitor_reset ='latch';
要禁用互斥量统计信息的收集,请运行:
SET GLOBAL innodb_monitor_disable ='latch';
互斥锁统计信息的集合
SHOW ENGINE INNODB
MUTEX也可以通过设置启用
innodb_monitor_enable='all',或通过设置禁用
innodb_monitor_disable='all'。
SHOW ENGINE INNODB
MUTEX 输出具有以下列:
Type
总是InnoDB。
Name
在MySQL 5.7.8之前,该Name字段会报告执行互斥锁的源文件以及创建互斥锁的文件中的行号。行号是特定于您的MySQL版本的。从MySQL 5.7.8开始,仅报告互斥体名称。文件名和行号仍然报告rwlocks。
Status
互斥状态。
在MySQL 5.7.8之前,Status如果WITH_DEBUG在MySQL编译时定义了该字段,则该字段会显示多个值
。如果
WITH_DEBUG未定义,则语句仅显示该os_waits
值。在后一种情况下(不含
WITH_DEBUG),输出信息不足以区分保护rwlocks(允许多个读者或单个作者)的常规互斥锁和互斥锁。因此,对于相同的互斥锁,输出可能看起来包含多行。Pre-MySQL 5.7.8 Status字段值包括:
count 表示请求了多少次互斥锁。
spin_waits 表示自旋锁必须运行多少次。
spin_rounds表示自旋锁回合的数量。(spin_rounds除以spin_waits提供平均回合数)。
os_waits指示操作系统等待的数量。这发生在自旋锁不起作用时(在自旋锁过程中互斥锁未被锁定,并且必须屈服于操作系统并等待)。
os_yields 指示尝试锁定互斥锁的线程放弃它的时间片并放到操作系统中的次数(假设允许其他线程运行将释放互斥锁,以便锁定它)。
os_wait_times指示在操作系统等待中花费的时间量(以毫秒为单位)。在MySQL 5.7中,时间被禁用,并且此值始终为0。
从MySQL 5.7.8开始,该Status字段将报告旋转次数,等待和调用次数。InnoDB没有报告在外部实施的低级别操作系统互斥体的统计信息。
spins 表示旋转次数。
waits 表示互斥等待的数量。
calls 表示请求了多少次互斥锁。
SHOW ENGINE INNODB MUTEX跳过
互斥和
RW-锁的
缓冲池块,作为输出的量可以在一个大缓冲池系统压倒性的。(每个16K缓冲池块中有一个互斥锁和一个rw锁,每千兆字节有65,536个块)
SHOW ENGINE INNODB MUTEX也未列出从未等待的互斥锁或rw锁(os_waits=0)。因此,SHOW ENGINE
INNODB MUTEX仅显示缓冲池外部已导致至少一个OS级别等待的互斥锁和rw锁的信息。
使用SHOW ENGINE
PERFORMANCE_SCHEMA STATUS检查绩效模式的代码的内部操作:
MySQL的> SHOW ENGINE PERFORMANCE_SCHEMA STATUS\G
...
*************************** 3. row ******************** *******
类型:performance_schema
名称:events_waits_history.size
状态:76
*************************** 4. row ******************** *******
类型:performance_schema
名称:events_waits_history.count
状态:10000
*************************** 5. row ******************** *******
类型:performance_schema
名称:events_waits_history.memory
状态:760000
...
*************************** 57. row ******************** *******
类型:performance_schema
名称:performance_schema.memory
状态:26459600
...
此声明旨在帮助DBA了解不同性能模式选项对内存要求的影响。
Name值由两部分组成,分别命名为内部缓冲区和缓冲区属性。解释缓冲区名称如下:
未公开为表的内部缓冲区在括号内命名。例子:
(pfs_cond_class).size,
(pfs_mutex_class).memory。
作为performance_schema数据库中的表而公开的内部缓冲区按照该表的
名称命名,不包含圆括号。例子:
events_waits_history.size,
mutex_instances.count。
作为一个整体适用于性能模式的值以开始performance_schema。例如:
performance_schema.memory。
缓冲区属性具有以下含义:
size是实现使用的内部记录的大小,例如表中行的大小。size值不能改变。
count是内部记录的数量,例如表中的行数。
count值可以使用性能架构配置选项进行更改。
对于表,
是产品tbl_name.memorysize和
count。对于整体性能模式,performance_schema.memory是所有使用的内存的总和(所有其他memory值的总和
)。
在某些情况下,性能模式配置参数与SHOW
ENGINE值之间存在直接关系。例如,
events_waits_history_long.count对应于
performance_schema_events_waits_history_long_size。在其他情况下,这种关系更为复杂。例如,
events_waits_history.count对应于
performance_schema_events_waits_history_size
(每个线程的行数)乘以
performance_schema_max_thread_instances
(线程数)。
显示引擎NDB状态。
如果服务器NDB启用了存储引擎,则SHOW ENGINE NDB STATUS
显示群集状态信息,例如连接的数据节点数,群集连接字符串和群集二进制日志历元,以及连接到MySQL服务器时创建的各种群集API对象的计数簇。此语句的输出示例如下所示:
MySQL的> SHOW ENGINE NDB STATUS;
+ ------------ + ------------ + ------------ -------------------------------------- +
| 类型| 名称| 状态|
+ ------------ + ------------ + ------------ -------------------------------------- +
| ndbcluster | 连接| cluster_node_id = 7,
connected_host = 198.51.100.103,connected_port = 1186,number_of_data_nodes = 4,
number_of_ready_data_nodes = 3,connect_count = 0 |
| ndbcluster | NdbTransaction | created = 6,free = 0,sizeof = 212 |
| ndbcluster | NdbOperation | created = 8,free = 8,sizeof = 660 |
| ndbcluster | NdbIndexScanOperation | created = 1,free = 1,sizeof = 744 |
| ndbcluster | NdbIndexOperation | created = 0,free = 0,sizeof = 664 |
| ndbcluster | NdbRecAttr | created = 1285,free = 1285,sizeof = 60 |
| ndbcluster | NdbApiSignal | created = 16,free = 16,sizeof = 136 |
| ndbcluster | NdbLabel | created = 0,free = 0,sizeof = 196 |
| ndbcluster | NdbBranch | created = 0,free = 0,sizeof = 24 |
| ndbcluster | NdbSubroutine | created = 0,free = 0,sizeof = 68 |
| ndbcluster | NdbCall | created = 0,free = 0,sizeof = 16 |
| ndbcluster | NdbBlob | created = 1,free = 1,sizeof = 264 |
| ndbcluster | NdbReceiver | created = 4,free = 0,sizeof = 68 |
| ndbcluster | binlog | latest_epoch = 155467,latest_trans_epoch = 148126,
latest_received_binlog_epoch = 0,latest_handled_binlog_epoch = 0,
latest_applied_binlog_epoch = 0 |
+ ------------ + ------------ + ------------ -------------------------------------- +
Status每行中
的列分别提供有关MySQL服务器与群集的连接以及群集二进制日志状态的信息。该Status信息是在逗号分隔的组的名称/值对的形式。
该connection行的
Status列包含下表中描述的名称/值对。
| 名称 | 值 |
|---|---|
cluster_node_id |
群集中MySQL服务器的节点ID |
connected_host |
MySQL服务器连接到的集群管理服务器的主机名或IP地址 |
connected_port |
MySQL服务器用来连接管理服务器的端口(connected_host) |
number_of_data_nodes |
为集群配置的数据节点数(即[ndbd]集群config.ini文件中的节
数) |
number_of_ready_data_nodes |
实际运行的群集中的数据节点数量 |
connect_count |
此mysqld连接或重新连接到群集数据节点的次数 |
该binlog行的
Status列包含有关NDB群集复制的信息。它包含的名称/值对在下表中进行了描述。
| 名称 | 值 |
|---|---|
latest_epoch |
最近在这台MySQL服务器上运行的最新时代(即服务器上运行的最近事务的序列号) |
latest_trans_epoch |
由集群的数据节点处理的最新时期 |
latest_received_binlog_epoch |
二进制日志线程收到的最新时期 |
latest_handled_binlog_epoch |
二进制日志线程处理的最新纪元(用于写入二进制日志) |
latest_applied_binlog_epoch |
实际写入二进制日志的最新时代 |
有关更多信息,请参见第21.6节“NDB群集复制”。
SHOW ENGINE NDB
STATUS以下列出
了其中最有可能证明可用于监视群集
的输出的其余行Name:
NdbTransaction:NdbTransaction已创建的对象的数量和大小
。一个NdbTransaction每次创建一个表模式操作(例如
CREATE TABLE或
ALTER TABLE)上执行NDB表。
NdbOperation:NdbOperation已创建的对象的数量和大小
。
NdbIndexScanOperation:NdbIndexScanOperation已创建的对象的数量和大小。
NdbIndexOperation:NdbIndexOperation已创建的对象的数量和大小
。
NdbRecAttr:NdbRecAttr已创建的对象的数量和大小
。通常,每当SQL节点执行数据操作语句时,都会创建其中一个。
NdbBlob:NdbBlob已创建的对象的数量和大小
。一个NdbBlob是对于涉及每个新创建的操作BLOB
在列NDB表。
NdbReceiver:NdbReceiver已创建的任何对象的数量和大小
。该created列中的数字与MySQL服务器连接到的集群中的数据节点数量相同。
SHOW ENGINE NDB STATUS如果NDB在访问运行此语句的SQL节点的MySQL客户端的当前会话期间没有执行涉及表的操作,则返回空结果
。
显示[存储]引擎
SHOW ENGINES显示有关服务器存储引擎的状态信息。这对于检查存储引擎是否受支持或查看默认引擎是特别有用的。这些信息也可以从INFORMATION_SCHEMA
ENGINES表格中获得
。请参见
第24.6节“INFORMATION_SCHEMA引擎表”。
MySQL的> SHOW ENGINES\G
*************************** 1. row ******************** *******
引擎:InnoDB
支持:默认
评论:支持事务,行级锁定和外键
交易:是
XA:是的
保存点:是
*************************** 2. row ******************** *******
引擎:MRG_MYISAM
支持:是
评论:收集相同的MyISAM表格
交易:NO
XA:NO
保存点:NO
*************************** 3. row ******************** *******
引擎:MEMORY
支持:是
评论:基于散列,存储在内存中,对临时表很有用
交易:NO
XA:NO
保存点:NO
*************************** 4. row ******************** *******
引擎:BLACKHOLE
支持:是
评论:/ dev / null存储引擎(您写入的任何内容都会消失)
交易:NO
XA:NO
保存点:NO
*************************** 5. row ******************** *******
引擎:MyISAM
支持:是
评论:MyISAM存储引擎
交易:NO
XA:NO
保存点:NO
*************************** 6. row ******************** *******
引擎:CSV
支持:是
评论:CSV存储引擎
交易:NO
XA:NO
保存点:NO
*************************** 7. row ******************** *******
引擎:ARCHIVE
支持:是
评论:存档存储引擎
交易:NO
XA:NO
保存点:NO
*************************** 8. row ******************** *******
引擎:PERFORMANCE_SCHEMA
支持:是
评论:性能模式
交易:NO
XA:NO
保存点:NO
*************************** 9. row ******************** *******
引擎:FEDERATED
支持:是
评论:联合MySQL存储引擎
交易:NO
XA:NO
保存点:NO
SHOW ENGINES根据所用的MySQL版本和其他因素
,输出可能会有所不同。Support列中显示的值表示服务器对存储引擎的支持级别,如下表所示。
| 值 | 含义 |
|---|---|
YES |
该引擎受支持并处于活动状态 |
DEFAULT |
就像YES,再加上这是默认引擎 |
NO |
该引擎不受支持 |
DISABLED |
该引擎已被支持,但已被禁用 |
值NO意味着服务器在不支持引擎的情况下被编译,因此无法在运行时启用。
的值DISABLED出现是因为服务器启动与关闭发动机,或者是因为不是所有的选项来启用它要求给予一个选项。在后一种情况下,错误日志应该包含一个说明为什么该选项被禁用的原因。请参见第5.4.2节“错误日志”。
DISABLED如果服务器被编译为支持它,
您也可以看到存储引擎,但是启动时带有一个
选项。
--skip-engine_name
所有MySQL服务器都支持MyISAM表格。这是不可能的MyISAM。
的Transactions,XA和
Savepoints列表示存储引擎是否分别支持事务,XA事务和保存点。
SHOW ERRORS [LIMIT [offset,]row_count] 显示计数(*)错误
SHOW ERRORS是一种类似于诊断的语句SHOW
WARNINGS,只是它仅显示错误信息,而不显示错误,警告和注释。
该LIMIT子句与语句的语法相同SELECT。请参见
第13.2.9节“SELECT语法”。
该SHOW COUNT(*)
ERRORS语句显示错误的数量。您也可以从error_count变量中检索这个数字
:
显示计数(*)错误; SELECT @@ error_count;
SHOW ERRORS并
error_count仅适用于错误,而不是警告或备注。在其他方面,它们与SHOW WARNINGSand
相似warning_count。特别是,
SHOW ERRORS不能显示超过
max_error_count消息的信息,并且
error_count可能超过max_error_count错误数量
超过的值max_error_count。
有关更多信息,请参见第13.7.5.40节“SHOW WARNINGS Syntax”。
展示活动
[{FROM | IN} schema_name]
[LIKE' pattern'| WHERE expr]
此语句显示有关事件管理器事件的信息。它要求EVENT从中显示事件的数据库的特权。
以最简单的形式SHOW EVENTS
列出当前模式中的所有事件:
MySQL的>SELECT CURRENT_USER(), SCHEMA();+ ---------------- + ---------- + | CURRENT_USER()| SCHEMA()| + ---------------- + ---------- + | jon @ ghidora | myschema | + ---------------- + ---------- + 一排(0.00秒) MySQL的>SHOW EVENTS\G*************************** 1. row ******************** ******* Db:myschema 名称:e_daily 定义者:jon @ ghidora 时区:SYSTEM 类型:RECURRING 执行在:NULL 间隔值:10 间隔字段:SECOND 开始于:2006-02-09 10:41:23 结束:NULL 状态:已启用 发起人:0 character_set_client:latin1 collation_connection:latin1_swedish_ci 数据库整理:latin1_swedish_ci
要查看特定模式的事件,请使用该
FROM子句。例如,要查看test模式的事件,请使用以下语句:
SHOW EVENTS FROM test;
该LIKE条款如果存在,表示要匹配哪些事件名称。如第24.34节“对SHOW语句的扩展”中WHERE所讨论的,可以使用该
子句使用更一般的条件来选择行
。
SHOW EVENTS 输出具有以下列:
Db:定义事件的模式(数据库)。
Name:事件的名称。
Time zone:事件时区,它是用于安排事件的时区,并且在事件执行时有效。默认值是
SYSTEM。
Definer:以
格式创建事件的用户的帐户
。
'user_name'@'host_name'
Type:事件重复类型,
ONE TIME(瞬态)或
RECURRING(重复)。
Execute At:瞬态事件设置为执行的日期和时间。显示为一个
DATETIME值。
对于重复性事件,此列的值始终为
NULL。
Interval Value:对于定期事件,事件执行之间要等待的时间间隔数。
对于瞬态事件,此列的值始终为
NULL。
Interval Field:重复事件在重复之前等待的时间间隔。
对于瞬态事件,此列的值始终为
NULL。
Starts:重复事件的开始日期和时间。这显示为一个
DATETIME值,并且
NULL如果没有为事件定义开始日期和时间。
对于瞬态事件,这个列总是
NULL。
Ends:重复事件的结束日期和时间。这显示为一个DATETIME值,NULL如果没有为事件定义结束日期和时间,则默认为该
值。
对于瞬态事件,这个列总是
NULL。
Status:事件状态。其中一个
ENABLED,DISABLED或
SLAVESIDE_DISABLED。
SLAVESIDE_DISABLED 表示事件的创建发生在另一台充当复制主服务器的MySQL服务器上,并复制到当前作为从服务器的MySQL服务器上,但事件目前未在从服务器上执行。
Originator:创建事件的MySQL服务器的服务器标识。默认为0。
character_set_client是character_set_client
创建例程时系统变量的会话值。
collation_connection是collation_connection
创建例程时系统变量的会话值。
Database Collation是与例程相关联的数据库的排序规则。
有关SLAVE_DISABLED和Originator列的更多信息,请参见
第16.4.1.16节“调用的功能的复制”。
事件操作语句未显示在输出中
SHOW EVENTS。使用
SHOW CREATE EVENT或
INFORMATION_SCHEMA.EVENTS表格。
显示的SHOW EVENTS
时间在事件时区中给出,如
第23.4.4节“事件元数据”中所述。
输出中SHOW
EVENTS的列与INFORMATION_SCHEMA.EVENTS表中的列类似,但不相同
。参见第24.7节“INFORMATION_SCHEMA事件表”。
显示功能状态
[LIKE' pattern'| WHERE expr]
该声明与SHOW PROCEDURE
STATUS存储的函数类似。请参见
第13.7.5.28节“SHOW PROCEDURE STATUS语法”。
SHOW GRANTS [FOR user]
此语句以GRANT必须执行以复制特权分配的语句的形式显示分配给MySQL用户帐户
的特权。
要显示MySQL帐户的非特权信息,请使用该SHOW CREATE USER语句。请参见第13.7.5.12节“SHOW CREATE USER语法”。
SHOW GRANTS需要
SELECT的特权
mysql数据库,除了为当前用户显示的特权。
要指定帐户名称SHOW
GRANTS,请使用与该帐户相同的格式
GRANT; 例如
'jeffrey'@'localhost':
MySQL的> SHOW GRANTS FOR 'jeffrey'@'localhost';
+ ------------------------------------------------- ----------------- +
| 赠款jeffrey @ localhost |
+ ------------------------------------------------- ----------------- +
| 授予*。*到'jeffrey` @`localhost` |的使用权
| GRANT SELECT,INSERT,UPDATE ON`db1`。* TO`jeffrey` @`localhost` |
+ ------------------------------------------------- ----------------- +
主机部分,如果省略,则默认为'%'。有关指定帐户名称的更多信息,请参见
第6.2.3节“指定帐户名称”。
要显示授予当前用户(您用于连接服务器的帐户)的权限,可以使用以下任何语句:
节目单; 显示CURRENT_USER的赠款; SHOW GRANTS FOR CURRENT_USER();
如果SHOW GRANTS FOR CURRENT_USER(或任何等效语法)用于定义者上下文中,例如在使用定义者而不是调用者特权执行的存储过程中),那么显示的定义是定义者而不是调用者。
SHOW GRANTS不显示可用于指定帐户但授予其他帐户的权限。例如,如果存在匿名帐户,则指定的帐户可能能够使用其权限,但SHOW GRANTS不显示它们。
SHOW GRANTS输出不包含
IDENTIFIED BY PASSWORD子句。SHOW CREATE USER改为使用该
语句。请参见第13.7.5.12节“SHOW CREATE USER语法”。
SHOW {INDEX | INDEXES | KEYS}
{FROM | IN} tbl_name
[{FROM | 在}db_name]
[WHERE expr]
SHOW INDEX返回表索引信息。该格式类似于SQLStatisticsODBC 中的
调用。此声明需要表中任何列的某些特权。
你可以使用
db_name。tbl_name
作为语法的替代
。这两个陈述是等同的:
tbl_name FROM
db_name
SHOW INDEX FROM mytable FROM mydb; SHOW INDEX FROM mydb.mytable;
如第24.34节“对SHOW语句的扩展”中WHERE所讨论的,可以使用该子句使用更一般的条件来选择行
。
MySQL的> SHOW INDEX FROM City\G
*************************** 1. row ******************** *******
表:城市
Non_unique:0
Key_name:PRIMARY
Seq_in_index:1
Column_name:ID
整理:A
基数:4321
Sub_part:NULL
已包装:NULL
空值:
Index_type:BTREE
评论:
Index_comment:
*************************** 2. row ******************** *******
表:城市
Non_unique:1
Key_name:CountryCode
Seq_in_index:1
Column_name:CountryCode
整理:A
基数:4321
Sub_part:NULL
已包装:NULL
空值:
Index_type:BTREE
评论:
Index_comment:
SHOW INDEX 返回以下字段:
Table
表格的名称。
Non_unique
如果索引不能包含重复项,则为0;如果可以,则为1。
Key_name
索引的名称。如果索引是主键,则名称始终为PRIMARY。
Seq_in_index
索引中的列序号,从1开始。
Column_name
列名称。
Collation
列如何在索引中排序。这可以有值
A(升序)或NULL
(不排序)。
Cardinality
估计索引中唯一值的数量。要更新此号码,请运行ANALYZE
TABLE或(for MyISAMtables)
myisamchk -a。
Cardinality根据以整数存储的统计信息进行计数,所以即使对于小型表格,该值也不一定准确。基数越高,MySQL在进行连接时使用索引的机会就越大。
Sub_part
索引前缀。也就是说,如果列只是部分索引的,NULL则索引字符的数量(
如果整列是索引的)。
前缀限制以字节为单位,而在前缀长度CREATE TABLE,
ALTER TABLE和
CREATE INDEX语句被解释为非二进制串类型的字符数(CHAR,
VARCHAR,
TEXT二进制串类型()和字节数BINARY,
VARBINARY,
BLOB)。为使用多字节字符集的非二进制字符串列指定前缀长度时,请考虑这一点。
有关索引前缀的更多信息,请参见 第8.3.4节“列索引”和 第13.1.14节“CREATE INDEX语法”。
Packed
指示密钥的打包方式。NULL如果不是。
Null
包含YES列是否包含NULL值,''如果不包含
。
Index_type
使用的索引方法(BTREE,
FULLTEXT,HASH,
RTREE)。
Comment
有关未在其自己的列中描述的索引的信息,例如disabled索引是否被禁用。
Index_comment
COMMENT在创建索引时为
具有属性的索引提供的任何注释
。
您还可以从中获取有关表索引的信息
INFORMATION_SCHEMA,其中包含一个
STATISTICS表。参见
第24.23节“INFORMATION_SCHEMA统计表”。
您可以使用mysqlshow -k
db_name
tbl_name命令列出表的索引。
SHOW MASTER STATUS
此语句提供有关主站的二进制日志文件的状态信息。它要求
SUPER或者
REPLICATION CLIENT特权。
例:
MySQL的> SHOW MASTER STATUS\G
*************************** 1. row ******************** *******
文件:master-bin.000002
职位:1307
Binlog_Do_DB:测试
Binlog_Ignore_DB:手动,mysql
Executed_Gtid_Set:3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5
一排(0.00秒)
全局事务ID正在使用时,
Executed_Gtid_Set显示已在主服务器上执行的事务的GTID集合。这与
gtid_executed此服务器上系统变量的值以及该服务器Executed_Gtid_Set输出中
的值相同
SHOW SLAVE STATUS。
显示打开的表格
[{FROM | 在}db_name]
[LIKE' pattern'| WHERE expr]
SHOW OPEN TABLES列出TEMPORARY当前在表缓存中打开的非表。请参见第8.4.3.1节“MySQL如何打开和关闭表”。该
FROM条款(如果存在)将显示的表限制为db_name
数据库中的表。该LIKE子句(如果存在)指示要匹配哪些表名。如第24.34节“对SHOW语句的扩展”中WHERE所讨论的,可以使用该
子句使用更一般的条件来选择行
。
SHOW OPEN TABLES 输出具有以下列:
Database
包含该表的数据库。
Table
表名。
In_use
表中有表锁或锁请求的数量。例如,如果一个客户端为一个表使用锁LOCK TABLE t1 WRITE,
In_use将为1.如果LOCK TABLE t1 WRITE在表保持锁定状态下另一个客户端发出问题,客户端将阻塞等待锁,但锁定请求In_use
为2.如果计数为零,表格已打开,但目前尚未使用。In_use也由HANDLER ...
OPEN声明增加
并减少了
HANDLER ...
CLOSE。
Name_locked
表名是否被锁定。名称锁定用于诸如删除或重命名表等操作。
如果您对表没有特权,则不会显示在输出中SHOW OPEN TABLES。
SHOW PLUGINS
SHOW PLUGINS显示关于服务器插件的信息。INFORMATION_SCHEMA.PLUGINS表中还提供了插件信息。请参见
第24.16节“INFORMATION_SCHEMA插件表”。
SHOW PLUGINS输出
示例:
MySQL的> SHOW PLUGINS\G
*************************** 1. row ******************** *******
名称:binlog
状态:ACTIVE
类型:存储引擎
库:NULL
许可证:GPL
*************************** 2. row ******************** *******
名称:CSV
状态:ACTIVE
类型:存储引擎
库:NULL
许可证:GPL
*************************** 3. row ******************** *******
名称:MEMORY
状态:ACTIVE
类型:存储引擎
库:NULL
许可证:GPL
*************************** 4. row ******************** *******
名称:MyISAM
状态:ACTIVE
类型:存储引擎
库:NULL
许可证:GPL
...
SHOW PLUGINS 输出具有以下列:
Name:用于在诸如INSTALL
PLUGIN和之类的语句中引用插件的名称UNINSTALL
PLUGIN。
Status:插件状态,一
ACTIVE,INACTIVE,
DISABLED,或DELETED。
Type:该类型的插件,如
STORAGE ENGINE,
INFORMATION_SCHEMA,或
AUTHENTICATION。
Library:插件共享库文件的名称。这是用来在诸如INSTALL
PLUGIN和之类的语句中引用插件文件的名称UNINSTALL
PLUGIN。该文件位于由plugin_dir
系统变量命名的目录中。如果库名称是
NULL,该插件被编译进来,无法卸载UNINSTALL
PLUGIN。
License:该插件如何获得许可; 例如GPL。
对于与之一起安装的插件INSTALL
PLUGIN,Name和
Library值也会在mysql.plugin表中注册
。
有关构成所显示信息基础的插件数据结构的信息SHOW
PLUGINS,请参见第28.2节“MySQL插件API”。
SHOW PRIVILEGES
SHOW PRIVILEGES显示MySQL服务器支持的系统权限列表。确切的权限列表取决于您的服务器的版本。
MySQL的> SHOW PRIVILEGES\G
*************************** 1. row ******************** *******
特权:改变
上下文:表
评论:改变表格
*************************** 2. row ******************** *******
特权:修改例程
上下文:函数,过程
评论:改变或删除存储的功能/程序
*************************** 3. row ******************** *******
特权:创建
上下文:数据库,表,索引
评论:创建新的数据库和表格
*************************** 4. row ******************** *******
特权:创建例程
上下文:数据库
注释:使用CREATE FUNCTION / PROCEDURE
*************************** 5. row ******************** *******
特权:创建临时表
上下文:数据库
评论:使用CREATE TEMPORARY TABLE
...
属于特定用户的权限由SHOW GRANTS语句显示
。有关更多信息,请参见
第13.7.5.21节“SHOW GRANTS语法”。
SHOW PROCEDURE CODE proc_name
这个语句是一个MySQL扩展,仅适用于已经使用调试支持构建的服务器。它显示指定的存储过程的内部实现的表示形式。类似的语句SHOW
FUNCTION CODE显示有关存储函数的信息(请参见第13.7.5.19节“SHOW FUNCTION CODE语法”)。
要使用任何一种语句,您必须是例程的所有者或有权SELECT访问
mysql.proc表。
如果指定的例程可用,则每个语句都会生成一个结果集。结果集中的每一行对应于例程中的一个
“ 指令 ”。第一列是
Pos从0开始的序号。第二列是Instruction,它包含一个SQL语句(通常从原始源代码改变而来),或者一个只对存储例程处理程序有意义的指令。
mysql>DELIMITER //mysql>CREATE PROCEDURE p1 ()- >BEGIN- >DECLARE fanta INT DEFAULT 55;- >DROP TABLE t2;- >LOOP- >INSERT INTO t3 VALUES (fanta);- >END LOOP;- >END//查询OK,0行受影响(0.00秒) MySQL的>SHOW PROCEDURE CODE p1//+ ----- + ---------------------------------------- + | Pos | 使用说明| + ----- + ---------------------------------------- + | 0 | 设置幻想@ 0 55 | | 1 | stmt 9“DROP TABLE t2”| | 2 | stmt 5“INSERT INTO t3 VALUES(fanta)”| | 3 | 跳转2 | + ----- + ---------------------------------------- + 4行(0.00秒)
在这个例子中,不可执行BEGIN和
END语句已经消失,并且对于
语句,只显示可执行部分(默认分配的部分)。对于从源获取的每条语句,都有一个代码字,后跟一个类型(9表示,5表示
,等等)。最后一行包含一条指令,意思是
。
DECLARE
variable_namestmtDROPINSERTjump 2GOTO instruction #2
SHOW PROCEDURE STATUS
[LIKE' pattern'| WHERE expr]
这个声明是一个MySQL扩展。它返回存储过程的特征,例如数据库,名称,类型,创建者,创建和修改日期以及字符集信息。类似的语句SHOW
FUNCTION STATUS显示有关存储函数的信息(请参见第13.7.5.20节“SHOW FUNCTION STATUS语法”)。
该LIKE条款(如果存在)指示要匹配哪些过程或函数名称。如第24.34节“对SHOW语句的扩展”中WHERE所讨论的,可以使用该
子句使用更一般的条件来选择行
。
MySQL的> SHOW PROCEDURE STATUS LIKE 'sp1'\G
*************************** 1. row ******************** *******
Db:测试
名称:sp1
类型:PROCEDURE
定义者:testuser @ localhost
修改时间:2004-08-03 15:29:37
创建日期:2004-08-03 15:29:37
Security_type:DEFINER
评论:
character_set_client:latin1
collation_connection:latin1_swedish_ci
数据库整理:latin1_swedish_ci
character_set_client是character_set_client创建例程时系统变量的会话值。
collation_connection是collation_connection创建例程时系统变量的会话值。Database
Collation是与例程相关联的数据库的排序规则。
您还可以从ROUTINES表中
获取有关存储例程的信息
INFORMATION_SCHEMA。请参见
第24.20节“INFORMATION_SCHEMA ROUTINES表”。
SHOW [FULL] PROCESSLIST
SHOW PROCESSLIST向您显示哪些线程正在运行。您还可以从INFORMATION_SCHEMA
PROCESSLIST表或
mysqladmin processlist命令中获取此信息
。如果您有PROCESS权限,则可以看到所有主题。否则,您只能看到自己的线程(即与您正在使用的MySQL帐户关联的线程)。如果您不使用FULL关键字,则只有每个语句的前100个字符显示在该
Info字段中。
过程信息也可从
performance_schema.threads表中找到。但是,访问threads不需要互斥,并且对服务器性能的影响最小。
INFORMATION_SCHEMA.PROCESSLIST并且SHOW PROCESSLIST由于它们需要互斥体而
具有负面的性能后果。
threads还显示有关后台线程,哪些信息
INFORMATION_SCHEMA.PROCESSLIST和
SHOW PROCESSLIST没有。这意味着threads可以用来监视其他线程信息源无法进行的活动。
SHOW PROCESSLIST如果你得到“ 连接太多 ”的
错误信息并想知道发生了什么,
该语句非常有用。MySQL保留一个额外的连接供具有该SUPER特权的帐户使用,以确保管理员应始终能够连接并检查系统(假设您没有将此特权授予所有用户)。
线程可以用KILL语句杀死
。请参见
第13.7.6.4节“KILL语法”。
以下是SHOW
PROCESSLIST输出示例:
mysql> SHOW FULL PROCESSLIST \ G
*************************** 1. row ******************** *******
Id:1
用户:系统用户
主办:
db:NULL
命令:连接
时间:1030455
状态:等待主人发送活动
信息:NULL
*************************** 2. row ******************** *******
Id:2
用户:系统用户
主办:
db:NULL
命令:连接
时间:1004
状态:已经读取所有的中继日志; 等待奴隶
I / O线程来更新它
信息:NULL
*************************** 3. row ******************** *******
Id:3112
用户:replikator
主持人:阿尔忒弥斯:2204
db:NULL
命令:Binlog转储
时间:2144
状态:已将所有binlog发送给从属; 等待binlog被更新
信息:NULL
*************************** 4. row ******************** *******
Id:3113
用户:replikator
主持人:iconnect2:45781
db:NULL
命令:Binlog转储
时间:2086年
状态:已将所有binlog发送给从属; 等待binlog被更新
信息:NULL
*************************** 5. row ******************** *******
Id:3123
用户:stefan
主机:localhost
db:apollon
命令:查询
时间:0
状态:NULL
信息:显示完整的进程列表
5行(0.00秒)
生成的列SHOW
PROCESSLIST具有以下含义:
连接标识符。这是在
表格ID列中
显示的相同类型的值,即Performance Schema
表格INFORMATION_SCHEMA.PROCESSLIST的PROCESSLIST_ID列,threads并由CONNECTION_ID()函数返回
。
发布该声明的MySQL用户。如果是这样
system user,它指的是服务器派生的非客户线程在内部处理任务。这可能是复制从服务器上使用的I / O或SQL线程或延迟行处理程序。unauthenticated
user指的是与客户端连接关联但客户端用户的身份验证尚未完成的线程。
event_scheduler指的是监视预定事件的线程。因为system
user,Host列中没有指定主机
。
发布该语句的客户端的主机名(除了system user没有主机的地方)。
SHOW PROCESSLIST以
格式报告TCP / IP连接的主机名,
以便更容易确定哪个客户端正在做什么。
host_name:client_port
默认数据库(如果选择了该数据库),否则
NULL。
线程正在执行的命令的类型。有关线程命令的说明,请参见
第8.14节“检查线程信息”。此列的值对应于
客户端/服务器协议和状态变量的
命令
。请参见第5.1.7节“服务器状态变量”COM_xxxCom_
xxx
线程处于当前状态的时间(以秒为单位)。对于从属SQL线程,该值是上次复制事件的时间戳与从属机器的实时之间的秒数。请参见 第16.2.2节“复制实现细节”。
指示线程正在执行的动作,事件或状态。有关State值的说明,请参见第8.14节“检查线程信息”。
大多数州相当于非常快速的操作。如果一个线程停留在一个给定的状态很多秒,可能有一个问题需要调查。
对于SHOW PROCESSLIST
声明,Stateis
的值NULL。
线程正在执行的语句,或者
NULL它没有执行任何语句。该语句可能是发送给服务器的语句,或者是语句执行其他语句时的最内层语句。例如,如果CALL
语句执行正在执行语句的存储过程,则
SELECT该
Info值将显示该
SELECT语句。
SHOW PROFILE [type[,type] ...] [查询n] [LIMITrow_count[OFFSEToffset]]type: 所有 | BLOCK IO | 上下文切换 | 中央处理器 | IPC | 记忆 | 页面故障 | 资源 | SWAPS
在SHOW PROFILE和
SHOW PROFILES报表显示剖析,表示当前会话过程中执行的语句资源使用信息。
这些语句已被弃用,并将在未来的MySQL版本中删除。改用 性能模式 ; 请参见 第25.18.1节“使用性能模式查询性能分析”。
分析由profiling会话变量控制,该
变量的默认值为0(OFF)。分析通过设置profiling为1或者
启用
ON:
MySQL的> SET profiling = 1;
SHOW PROFILES显示发送到服务器的最新语句的列表。列表大小由profiling_history_size会话变量控制,
默认值为15.最大值为100.将值设置为0具有禁用分析的实际效果。
除了SHOW
PROFILE和SHOW
PROFILES,所有语句都将进行概要分析,因此您不会在概要文件列表中找到这些语句。格式错误的陈述被描述。例如,SHOW PROFILING是非法声明,如果尝试执行它,则会出现语法错误,但会显示在分析列表中。
SHOW PROFILE显示关于单个语句的详细信息。如果没有该子句,则输出属于最近执行的语句。如果
包含,则显示声明的信息。与显示的值对应的
值
。
FOR
QUERY nFOR QUERY nSHOW PROFILEnnQuery_IDSHOW PROFILES
该条款可能会将输出限制为
行。如果
给出,可以添加到开始输出行到整个行集。
LIMIT
row_countrow_countLIMITOFFSET
offsetoffset
默认情况下,SHOW PROFILE显示
Status和Duration
列。这些Status值与所State显示
的值相似
SHOW PROCESSLIST,但对于某些状态值的两种语句的解释可能存在一些细微差异(请参见
第8.14节“检查线程信息”)。
type可以指定
可选值以显示特定的其他类型的信息:
ALL 显示所有信息
BLOCK IO 显示块输入和输出操作的计数
CONTEXT SWITCHES 显示自愿和非自愿上下文切换的计数
CPU 显示用户和系统CPU使用时间
IPC 显示发送和接收消息的计数
MEMORY 目前尚未实施
PAGE FAULTS 显示主要和次要页面错误的计数
SOURCE 显示源代码中函数的名称,以及函数所在文件的名称和行号
SWAPS 显示交换次数
每次会话都启用分析。会话结束时,其分析信息将丢失。
MySQL的>SELECT @@profiling;+ ------------- + | @@分析| + ------------- + | 0 | + ------------- + 一排(0.00秒) MySQL的>SET profiling = 1;查询OK,0行受影响(0.00秒) MySQL的>DROP TABLE IF EXISTS t1;查询确定,0行受影响,1个警告(0.00秒) MySQL的>CREATE TABLE T1 (id INT);查询OK,0行受影响(0.01秒) MySQL的>SHOW PROFILES;+ ---------- + ---------- + -------------------------- + | Query_ID | 持续时间| 查询| + ---------- + ---------- + -------------------------- + | 0 | 0.000088 | SET PROFILING = 1 | | 1 | 0.000136 | DROP TABLE IF EXISTS t1 | | 2 | 0.011947 | CREATE TABLE t1(id INT)| + ---------- + ---------- + -------------------------- + 设置3行(0.00秒) MySQL的>SHOW PROFILE;+ ---------------------- + ---------- + | 状态| 持续时间| + ---------------------- + ---------- + | 检查权限| 0.000040 | | 创建表| 0.000056 | | 创建|后 0.011363 | | 查询结束| 0.000375 | | 释放物品| 0.000089 | | 日志缓慢查询| 0.000019 | | 清理| 0.000005 | + ---------------------- + ---------- + 设置7行(0.00秒) MySQL的>SHOW PROFILE FOR QUERY 1;+ -------------------- + ---------- + | 状态| 持续时间| + -------------------- + ---------- + | 查询结束| 0.000107 | | 释放物品| 0.000008 | | 日志缓慢查询| 0.000015 | | 清理| 0.000006 | + -------------------- + ---------- + 4行(0.00秒) MySQL的>SHOW PROFILE CPU FOR QUERY 2;+ ---------------------- + ---------- + ---------- + ---- -------- + | 状态| 持续时间| CPU_user | CPU_system | + ---------------------- + ---------- + ---------- + ---- -------- + | 检查权限| 0.000040 | 0.000038 | 0.000002 | | 创建表| 0.000056 | 0.000028 | 0.000028 | | 创建|后 0.011363 | 0.000217 | 0.001571 | | 查询结束| 0.000375 | 0.000013 | 0.000028 | | 释放物品| 0.000089 | 0.000010 | 0.000014 | | 日志缓慢查询| 0.000019 | 0.000009 | 0.000010 | | 清理| 0.000005 | 0.000003 | 0.000002 | + ---------------------- + ---------- + ---------- + ---- -------- + 设置7行(0.00秒)
性能分析在某些体系结构上只能部分运行。对于依赖于getrusage()
系统调用的值,NULL将在不支持该调用的Windows等系统上返回。另外,分析是按进程进行的,而不是针对每个线程。这意味着服务器中除您自己以外的线程上的活动可能会影响您看到的时间信息。
您还可以从PROFILING表格中
获取分析信息
INFORMATION_SCHEMA。请参见
第24.18节“INFORMATION_SCHEMA概要表”。例如,以下查询产生相同的结果:
QUERY 2的展示简介; 选择状态,格式(持续时间,6)作为持续时间 FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID = 2 ORDER BY SEQ;
SHOW PROFILES
该SHOW PROFILES声明与SHOW PROFILE显示分析信息一起显示了在当前会话期间执行的语句的资源使用情况。有关更多信息,请参见第13.7.5.30节“SHOW PROFILE语法”。
这些语句已被弃用,并将在未来的MySQL版本中删除。改用性能模式; 请参阅 第25章MySQL性能架构。
显示继电器事件
[IN' log_name']
[FROM pos]
[LIMIT [ offset,] row_count]
[ channel_option]
channel_option:
对于频道 channel
显示复制从站的中继日志中的事件。如果你没有指定
',则显示第一个中继日志。该声明对主人没有影响。
log_name'
该LIMIT子句与语句的语法相同SELECT。请参见
第13.2.9节“SELECT语法”。
由于服务器向客户端返回中继日志的完整内容(包括修改从服务器接收到的数据的所有语句),因此
发出不SHOW RELAYLOG EVENTS
带LIMIT子句可能会导致非常耗费时间和资源的过程。
可选子句使您能够命名该语句适用于哪个复制通道。提供子句将语句应用于特定的复制通道。如果没有通道被命名并且不存在额外的通道,则该语句适用于默认通道。
FOR CHANNEL
channelFOR CHANNEL
channel
使用多个复制通道时,如果SHOW RELAYLOG EVENTS语句未使用子句定义通道,则会
生成错误。有关更多信息,请参见第16.2.3节“复制通道”。
FOR CHANNEL
channel
SHOW RELAYLOG EVENTS 显示中继日志中每个事件的以下字段:
Log_name
正在列出的文件的名称。
Pos
事件发生的位置。
Event_type
描述事件类型的标识符。
Server_id
发生事件的服务器的服务器ID。
End_log_pos
值End_log_pos此事件在主人的二进制日志。
Info
有关事件类型的更多详细信息。这些信息的格式取决于事件类型。
某些与设置用户和系统变量有关的事件不包括在输出中
SHOW RELAYLOG EVENTS。要获得中继日志中事件的完整覆盖,请使用
mysqlbinlog。
显示奴隶主
显示当前在主站中注册的复制从站列表。
SHOW SLAVE HOSTS应该在充当复制主服务器的服务器上执行。该语句显示有关已连接或已连接为复制从服务器的服务器的信息,每行结果对应于一个从服务器,如下所示:
mysql> SHOW SLAVE HOSTS;
+ ------------ + ----------- ------ + + ----------- + ----- --------------------------------- +
| Server_id | 主机| 端口| Master_id | Slave_UUID |
+ ------------ + ----------- ------ + + ----------- + ----- --------------------------------- +
| 192168010 | iconnect2 | 3306 | 192168011 | 14cb6624-7f93-11e0-b2c0-c80aa9429562 |
| 1921680101 | athena | 3306 | 192168011 | 07af4990-f41f-11df-a566-7ac56fdaf645 |
+ ------------ + ----------- ------ + + ----------- + ----- --------------------------------- +
Server_id:从服务器的唯一服务器ID,如从服务器的选件文件中配置的那样,或者在命令行中使用
。
--server-id=value
Host:使用该--report-host选项在从站上指定的从站服务器的主机名
。这可能与操作系统中配置的计算机名称不同。
User:从站服务器用户名称,在从站上用--report-user选项指定
。仅当主服务器使用该--show-slave-auth-info
选项启动时,语句输出才包含此列
。
Password:从机服务器密码为,在从机上用--report-password选项指定
。仅当主服务器使用该--show-slave-auth-info
选项启动时,语句输出才包含此列
。
Port:从属服务器正在监听的主站上的端口,如从站上指定的端口 --report-port选项。
此列中的零表示--report-port未设置从端口()。
Master_id:从服务器从中复制的主服务器的唯一服务器标识。这是执行的服务器的服务器ID SHOW
SLAVE HOSTS,因此结果中的每一行都会列出相同的值。
显示从属状态[用于通道channel]
此语句提供有关从属线程基本参数的状态信息。它要求
SUPER或者
REPLICATION CLIENT特权。
如果您使用mysql
客户端发布此语句,则可以使用\G语句终止符而不是分号来获得更易读的垂直布局:
MySQL的> SHOW SLAVE STATUS\G
*************************** 1. row ******************** *******
Slave_IO_State:等待主控发送事件
Master_Host:本地主机
Master_User:根
Master_Port:13000
Connect_Retry:60
Master_Log_File:master-bin.000002
Read_Master_Log_Pos:1307
Relay_Log_File:slave-relay-bin.000003
Relay_Log_Pos:1508
Relay_Master_Log_File:master-bin.000002
Slave_IO_Running:是的
Slave_SQL_Running:是的
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno:0
Last_Error:
Skip_Counter:0
Exec_Master_Log_Pos:1307
Relay_Log_Space:1858
Until_Condition:无
Until_Log_File:
Until_Log_Pos:0
Master_SSL_Allowed:否
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master:0
Master_SSL_Verify_Server_Cert:没有
Last_IO_Errno:0
Last_IO_Error:
Last_SQL_Errno:0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id:1
Master_UUID:3e11fa47-71ca-11e1-9e33-c80aa9429562
Master_Info_File:/var/mysqld.2/data/master.info
SQL_Delay:0
SQL_Remaining_Delay:NULL
Slave_SQL_Running_State:从中继日志中读取事件
Master_Retry_Count:10
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:3e11fa47-71ca-11e1-9e33-c80aa9429562:1-5
Executed_Gtid_Set:3e11fa47-71ca-11e1-9e33-c80aa9429562:1-5
Auto_Position:1
Replicate_Rewrite_DB:
CHANNEL_NAME:
Master_TLS_版本:TLSv1.2
性能模式提供了公开复制信息的表。这与SHOW SLAVE STATUS声明中提供的信息类似,但以表格形式表示。有关详细信息,请参见
第25.11.11节“性能架构复制表”。
以下列表描述了返回的字段
SHOW SLAVE STATUS。有关解释其含义的更多信息,请参见
第16.1.7.1节“检查复制状态”。
Slave_IO_State
从I / O线程State的SHOW PROCESSLIST输出字段的
副本。这会告诉你线程正在做什么:尝试连接到主服务器,等待来自主服务器的事件,重新连接到主服务器等等。有关可能状态的列表,请参见
第8.14.5节“复制从器件I / O线程状态”。
Master_Host
主机与主机连接。
Master_User
用于连接到主服务器的帐户的用户名。
Master_Port
用于连接到主站的端口。
Connect_Retry
连接重试之间的秒数(默认值为60)。这可以通过CHANGE MASTER
TO声明进行设置。
Master_Log_File
I / O线程当前正在读取的主二进制日志文件的名称。
Read_Master_Log_Pos
I / O线程读取的当前主二进制日志文件中的位置。
Relay_Log_File
SQL线程当前正在读取和执行的中继日志文件的名称。
Relay_Log_Pos
SQL线程读取并执行的当前中继日志文件中的位置。
Relay_Master_Log_File
包含由SQL线程执行的最新事件的主二进制日志文件的名称。
Slave_IO_Running
I / O线程是否已启动并已成功连接到主站。在内部,该线程的状态由以下三个值之一表示:
MYSQL_SLAVE_NOT_RUN。
从I / O线程未运行。对于这个状态,
Slave_IO_Running是
No。
MYSQL_SLAVE_RUN_NOT_CONNECT。
从属I / O线程正在运行,但未连接到复制主节点。对于这个状态,
Slave_IO_Running是
Connecting。
MYSQL_SLAVE_RUN_CONNECT。
从I / O线程正在运行,并连接到复制主服务器。对于这个状态,
Slave_IO_Running是
Yes。
所述的值
Slave_running系统状态变量对应于该值。
Slave_SQL_Running
SQL线程是否启动。
Replicate_Do_DB,
Replicate_Ignore_DB
使用--replicate-do-db和
--replicate-ignore-db
选项指定的数据库列表(
如果有的话)。
Replicate_Do_Table,
Replicate_Ignore_Table,
Replicate_Wild_Do_Table,
Replicate_Wild_Ignore_Table
与中指定的表的清单
--replicate-do-table,
--replicate-ignore-table,
--replicate-wild-do-table,和
--replicate-wild-ignore-table
如果任何选项。
Last_Errno, Last_Error
这些列是Last_SQL_Errno和的
别名
Last_SQL_Error。
发布RESET MASTER或
RESET SLAVE重置这些列中显示的值。
当从属SQL线程收到错误时,它首先报告错误,然后停止SQL线程。这意味着,即使仍然显示
,仍有一小段时间
SHOW SLAVE STATUS显示非零值。
Last_SQL_ErrnoSlave_SQL_RunningYes
Skip_Counter
sql_slave_skip_counter
系统变量
的当前值
。请参见
第13.4.2.5节“SET GLOBAL sql_slave_skip_counter语法”。
Exec_Master_Log_Pos
SQL线程读取并执行的当前主二进制日志文件中的位置,标记要处理的下一个事务或事件的开始。从现有的从站启动新的从站时,可以将该值与CHANGE MASTER
TO语句的
MASTER_LOG_POS选项一起使用,以便新的从站从该点读取数据。主控二进制日志中由(Relay_Master_Log_File,
Exec_Master_Log_Pos)给出的坐标对应于(Relay_Log_File,
Relay_Log_Pos在中继日志)。
来自中继日志的已执行的事务序列中的不一致可能导致此值成为“ 低水位标记 ”。换句话说,出现在头寸之前的交易被保证承诺,但头寸之后的交易可能已经承诺或没有承诺。如果需要纠正这些差距,请使用
START SLAVE
UNTIL SQL_AFTER_MTS_GAPS。有关
更多信息,请参见
第16.4.1.33节“复制和事务不一致性”。
Relay_Log_Space
所有现有中继日志文件的总大小。
Until_Condition,
Until_Log_File,
Until_Log_Pos
声明UNTIL条款中
指定的值START SLAVE。
Until_Condition 有这些值:
None如果没有UNTIL
指定任何子句
Master 如果从站正在读取,直到主站的二进制日志中的给定位置
Relay 如果从站正在读取,直到其中继日志中的给定位置
SQL_BEFORE_GTIDS如果从属SQL线程正在处理事务,直到它到达其中列出GTID的第一个事务
gtid_set。
SQL_AFTER_GTIDS如果从属线程正在处理所有事务,直到gtid_set两个线程处理完最后一个事务为止。
SQL_AFTER_MTS_GAPS
如果多线程从属的SQL线程正在运行,直到在中继日志中找不到更多间隔。
Until_Log_File并
Until_Log_Pos指出定义SQL线程停止执行的坐标的日志文件名称和位置。
有关UNTIL子句的更多信息,请参见第13.4.2.6节“START SLAVE语法”。
Master_SSL_Allowed,
Master_SSL_CA_File,
Master_SSL_CA_Path,
Master_SSL_Cert,
Master_SSL_Cipher,
Master_SSL_CRL_File,
Master_SSL_CRL_Path,
Master_SSL_Key,
Master_SSL_Verify_Server_Cert
这些字段显示从设备连接到主设备时使用的SSL参数(如果有的话)。
Master_SSL_Allowed 有这些值:
Yes 如果允许与主站的SSL连接
No 如果与主站的SSL连接不被允许
Ignored 如果允许SSL连接但从服务器未启用SSL支持
其他SSL相关的字段的值对应的值MASTER_SSL_CA,
MASTER_SSL_CAPATH,
MASTER_SSL_CERT,
MASTER_SSL_CIPHER,
MASTER_SSL_CRL,
MASTER_SSL_CRLPATH,
MASTER_SSL_KEY,和
MASTER_SSL_VERIFY_SERVER_CERT选项的CHANGE MASTER TO
说法。请参见第13.4.2.1节“更改MASTER TO语法”。
Seconds_Behind_Master
该字段表示奴隶“ 迟到 ”的情况:
当从站正在处理更新时,此字段显示从站上当前时间戳与主站上当前正在从站上处理的事件上记录的原始时间戳之间的差异。
当从机上当前没有处理事件时,该值为0。
本质上,该字段用于度量从属SQL线程和从属I / O线程之间的时间差(以秒为单位)。如果主站和从站之间的网络连接速度很快,则从站I / O线程与主站非常接近,所以此字段很好地近似了从站SQL线程与主站进行比较的时间。如果网络很慢,这不是一个好的近似; 从属SQL线程可能经常被慢速读取从属I / O线程所困扰,因此Seconds_Behind_Master即使I / O线程比主节点晚,
通常也会显示值0。换句话说,这一列仅适用于快速网络。
即使主时钟和从时钟的时钟时间不相同,只要从I / O线程启动时计算出的时间差从此保持不变,即使时间差计算也能正常工作。任何更改(包括NTP更新)都可能导致时钟偏移,从而导致计算Seconds_Behind_Master可靠性降低。
在MySQL 5.7中,NULL如果从属SQL线程未运行,或者SQL线程已占用所有中继日志且从属I / O线程未运行,则此字段为
(未定义或未知)。(在旧版本的MySQL,这个领域
NULL,如果从SQL线程或从I / O线程不运行或不连接到主。)如果I / O线程正在运行,但中继日志被耗尽,Seconds_Behind_Master是设置为0。
值的Seconds_Behind_Master基础是存储在事件中的时间戳,这些事件通过复制保留。这意味着如果主设备M1本身就是M0的从设备,那么源自M0二进制日志的M1二进制日志中的任何事件都将具有该事件的M0时间戳。这使MySQL能够TIMESTAMP成功复制
。然而,问题
Seconds_Behind_Master是如果M1也接收到来自客户端的直接更新,则该
Seconds_Behind_Master值随机波动,因为有时来自M1的最后事件源自M0并且有时是M1上的直接更新的结果。
在使用多线程从机时,请记住此值基于此值
Exec_Master_Log_Pos,因此可能无法反映最近提交的事务的位置。
Last_IO_Errno,
Last_IO_Error
导致I / O线程停止的最新错误的错误号和错误消息。错误编号0和空字符串的消息表示“ 没有错误。“如果该Last_IO_Error值不为空,则错误值也会出现在从站的错误日志中。
I / O错误信息包括显示最近发生I / O线程错误的时间戳。此时间戳使用该格式YYMMDD HH:MM:SS,并显示在Last_IO_Error_Timestamp列中。
发布RESET MASTER或
RESET SLAVE重置这些列中显示的值。
Last_SQL_Errno,
Last_SQL_Error
导致SQL线程停止的最新错误的错误号和错误消息。错误编号0和空字符串的消息表示“ 没有错误。“如果该Last_SQL_Error值不为空,则错误值也会出现在从站的错误日志中。
如果从站是多线程的,则SQL线程是工作线程的协调器。在这种情况下,该
Last_SQL_Error字段显示Last_Error_Message“性能架构” replication_applier_status_by_coordinator
表中的列
显示的内容。字段值被修改以表明其他工作线程中可能出现更多故障,这可以在replication_applier_status_by_worker
显示每个工作线程状态的表中看到
。如果该表不可用,则可以使用从站错误日志。replication_applier_status_by_worker
还应该使用日志或
表格来了解有关SHOW SLAVE STATUS协调器表所显示的故障的更多信息。
SQL错误信息包括显示最新SQL线程错误发生时间的时间戳。此时间戳使用格式YYMMDD HH:MM:SS,并显示在Last_SQL_Error_Timestamp列中。
发布RESET MASTER或
RESET SLAVE重置这些列中显示的值。
在MySQL 5.7中,Last_SQL_Errno和
Last_SQL_Error列中显示的所有错误代码和消息对应于B.3节“服务器错误代码和消息”中列出的错误值
。这在以前的版本中并不总是如此。(错误#11760365,错误#52768)
Replicate_Ignore_Server_Ids
在MySQL 5.7中,您使用语句的IGNORE_SERVER_IDS选项
将从服务器设置为忽略来自0个或更多主服务器的事件
CHANGE MASTER TO。默认情况下,它是空白的,并且通常仅在使用循环或其他多主复制设置时才进行修改。显示Replicate_Ignore_Server_Ids何时非空白的消息
由逗号分隔的一个或多个数字列表组成,表示要忽略的服务器ID。例如:
Replicate_Ignore_Server_Ids:2,6,9
Ignored_server_ids还显示要忽略的服务器标识,但是是以空格分隔的列表,其前面是要忽略的服务器标识的总数。例如,如果CHANGE
MASTER TO包含该IGNORE_SERVER_IDS = (2,6,9)选项的语句
已经发出以告诉从属服务器忽略具有服务器ID 2,6或9的主服务器,则该信息如下所示:
Ignored_server_ids:3,2,6,9
第一个数字(在这种情况下3)显示被忽略的服务器ID的数量。
Replicate_Ignore_Server_Ids过滤由I / O线程执行,而不是由SQL线程执行,这意味着过滤掉的事件不会写入中继日志。这与服务器选项所采用的筛选动作不同,这些选项
--replicate-do-table适用于SQL线程。
Master_Server_Id
server_id来自主人
的价值。
Master_UUID
server_uuid来自主人
的价值。
Master_Info_File
master.info文件
的位置。
SQL_Delay
从站必须滞后主站的秒数。
SQL_Remaining_Delay
如果Slave_SQL_Running_State是
Waiting until MASTER_DELAY seconds after master
executed event,则此字段包含的剩余延迟秒数。在其他时候,这个领域是
NULL。
Slave_SQL_Running_State
SQL线程的状态(类似于
Slave_IO_State)。该值与State显示的SQL线程的值相同SHOW
PROCESSLIST。
第8.14.6节“复制从SQL SQL线程状态”提供了可能状态的列表
Master_Retry_Count
在连接丢失的情况下,从设备可以尝试重新连接到主设备的次数。可以使用语句MASTER_RETRY_COUNT
选项CHANGE MASTER
TO(首选)或较旧的
--master-retry-count服务器选项(仍支持向后兼容性)来设置此值。
Master_Bind
从站绑定的网络接口(如果有的话)。这是使用MASTER_BIND该CHANGE MASTER TO
语句的选项设置的。
Last_IO_Error_Timestamp
YYMMDD HH:MM:SS格式化
的时间戳,显示最近发生I / O错误的时间。
Last_SQL_Error_Timestamp
YYMMDD HH:MM:SS格式化
的时间戳,显示最后一次SQL错误发生的时间。
Retrieved_Gtid_Set
全局事务标识的集合对应于该从站收到的所有事务。如果GTID未被使用,则为空。有关更多信息,请参阅 GTID集。
这是继电器日志中存在或已存在的所有GTID的集合。每Gtid_log_event收到一个GTID都会立即添加
。这可能会导致部分传输的事务将其GTID包含在集合中。
当所有中继日志由于执行RESET SLAVE或
CHANGE MASTER TO由于--relay-log-recovery选项的影响而
丢失时
,该组被清除。何时
relay_log_purge = 1,最新的中继日志始终保留,并且该集合未被清除。
Executed_Gtid_Set
写在二进制日志中的一组全局事务ID。这与gtid_executed此服务器上全局
系统变量的值以及此服务器Executed_Gtid_Set输出中
的值相同
SHOW MASTER STATUS。如果GTID未被使用,则为空。有关更多信息,请参阅
GTID集。
Auto_Position
1如果自动定位正在使用中; 否则为0。
Replicate_Rewrite_DB
该Replicate_Rewrite_DB值显示指定的所有复制过滤规则。例如,如果设置了以下复制筛选器规则:
更改复制过滤器REPLICATE_REWRITE_DB =((db1,db2),(db3,db4));
该Replicate_Rewrite_DB值显示:
Replicate_Rewrite_DB:(db1,db2),(db3,db4)
有关更多信息,请参见 第13.4.2.2节“更改复制过滤器语法”。
Channel_name
正在显示的复制通道。总是有一个默认的复制通道,可以添加更多的复制通道。有关更多信息,请参见 第16.2.3节“复制通道”。
Master_TLS_Version
主设备上使用的TLS版本。有关TLS版本信息,请参见 第6.4.6节“加密连接协议和密码”。该列已添加到MySQL 5.7.10中。
SHOW [GLOBAL | SESSION]状态
[LIKE' pattern'| WHERE expr]
从MySQL 5.7.6开始,show_compatibility_56系统变量的值
影响这里描述的语句所需的信息和所需的权限。有关详细信息,请参见第5.1.5节“服务器系统变量”中对该变量的描述
。
SHOW STATUS提供服务器状态信息(请参见
第5.1.7节“服务器状态变量”)。该声明不需要任何特权。它只需要连接到服务器的能力。
状态变量信息也可以从这些来源获得:
对于SHOW STATUS,一个
LIKE子句(如果存在)指示要匹配哪些变量名称。如第24.34节“SHOW语句的扩展”中WHERE所讨论的,可以使用一个子句来使用更一般的条件来选择行。
SHOW STATUS接受可选
GLOBAL或SESSION可变范围修改器:
使用GLOBAL修饰符,该语句显示全局状态值。全局状态变量可以表示服务器本身某些方面的状态(例如Aborted_connects),或者表示与MySQL的所有连接(例如Bytes_received和
Bytes_sent)的聚合状态。如果变量没有全局值,则显示会话值。
使用SESSION修饰符,该语句显示当前连接的状态变量值。如果变量没有会话值,则显示全局值。LOCAL是一个同义词SESSION。
如果不存在修饰符,则默认为
SESSION。
第5.1.7节“服务器状态变量” 列出了每个状态变量的作用域 。
SHOW
STATUS语句的
每次调用都使用一个内部临时表并增加全局
Created_tmp_tables值。
部分输出显示在这里。您的服务器的名称和值列表可能会有所不同。第5.1.7节“服务器状态变量”给出了每个变量的含义 。
MySQL的> SHOW STATUS;
+ -------------------------- + ------------ +
| 变量名| 值|
+ -------------------------- + ------------ +
| Aborted_clients | 0 |
| Aborted_connects | 0 |
| Bytes_received | 155372598 |
| Bytes_sent | 1176560426 |
| 连接| 30023 |
| Created_tmp_disk_tables | 0 |
| Created_tmp_tables | 8340 |
| Created_tmp_files | 60 |
...
| Open_tables | 1 |
| Open_files | 2 |
| Open_streams | 0 |
| Opened_tables | 44600 |
| 问题| 2026873 |
...
| Table_locks_immediate | 1920382 |
| Table_locks_waited | 0 |
| Threads_cached | 0 |
| Threads_created | 30022 |
| Threads_connected | 1 |
| Threads_running | 1 |
| 正常运行时间| 80380 |
+ -------------------------- + ------------ +
使用LIKE子句时,语句仅显示名称与模式匹配的变量的行:
MySQL的> SHOW STATUS LIKE 'Key%';
+ -------------------- + ---------- +
| 变量名| 值|
+ -------------------- + ---------- +
| Key_blocks_used | 14955 |
| Key_read_requests | 96854827 |
| Key_reads | 162040 |
| Key_write_requests | 7589728 |
| Key_writes | 3813196 |
+ -------------------- + ---------- +
SHOW TABLE STATUS
[{FROM | IN} db_name]
[LIKE' pattern'| WHERE expr]
SHOW TABLE STATUS作品喜欢
SHOW TABLES,但提供了很多关于每个非TEMPORARY
表格的信息。您也可以使用mysqlshow --statusdb_name命令获取此列表。该LIKE子句(如果存在)指示要匹配哪些表名。如第24.34节“对SHOW语句的扩展”中WHERE所讨论的,可以使用该
子句使用更一般的条件来选择行
。
该声明还显示有关视图的信息。
SHOW TABLE STATUS 输出具有以下列:
Name
表格的名称。
Engine
表格的存储引擎。请参阅 第15章,备用存储引擎。
Version
表格.frm
文件的版本号。
Row_format
该行的存储格式(Fixed,
Dynamic,Compressed,
Redundant,Compact)。对于MyISAM表,
Dynamic对应于
myisamchk -dvv报告的内容
Packed。InnoDB表格格式是Redundant或者
Compact当使用
Antelope文件格式时,
Compressed或者Dynamic
当使用Barracuda文件格式时。
Rows
行数。一些存储引擎(例如
MyISAM)存储确切的计数。对于其他存储引擎,如此InnoDB值是一个近似值,并且可能与实际值相差多达40%到50%。在这种情况下,用于
SELECT COUNT(*)获得准确的计数。
该Rows值NULL
用于INFORMATION_SCHEMA
数据库中的表。
Avg_row_length
平均行长。
Data_length
因为MyISAM,
Data_length是数据文件的长度,以字节为单位。
对于InnoDB,
Data_length是为聚簇索引分配的近似内存量(以字节为单位)。具体来说,聚合索引大小(以页面为单位)乘以InnoDB页面大小。
有关其他存储引擎的信息,请参阅本节末尾的注释。
Max_data_length
因为MyISAM,
Max_data_length是数据文件的最大长度。这是在给定使用的数据指针大小的情况下可以存储在表中的数据的总字节数。
未使用InnoDB。
有关其他存储引擎的信息,请参阅本节末尾的注释。
Index_length
对于MyISAM,
Index_length是索引文件的长度,以字节为单位。
对于InnoDB,
Index_length是为非聚集索引分配的近似内存量(以字节为单位)。具体来说,它是非聚集索引大小的总和,以页面大小乘以InnoDB页面大小。
有关其他存储引擎的信息,请参阅本节末尾的注释。
Data_free
已分配但未使用的字节数。
这些信息也显示在InnoDB
表格中(以前,它是在Comment
值中)。InnoDB表报告表所属表空间的可用空间。对于位于共享表空间中的表,这是共享表空间的可用空间。如果您使用多个表空间并且该表具有自己的表空间,则可用空间仅适用于该表。可用空间意味着完全空闲范围内的字节数减去安全余量。即使可用空间显示为0,只要不需要分配新扩展数据块,也可以插入行。
对于分区表,这个值只是一个估计值,可能不是绝对正确的。在这种情况下获取此信息的更准确的方法是查询
INFORMATION_SCHEMA.PARTITIONS表,如下例所示:
SELECT SUM(DATA_FREE)
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA ='mydb'
AND TABLE_NAME ='mytable';
有关更多信息,请参见 第24.15节“INFORMATION_SCHEMA分区表”。
Auto_increment
下一个AUTO_INCREMENT值。
Create_time
表创建时。
Update_time
数据文件上次更新时。对于某些存储引擎,这个值是NULL。例如,
InnoDB在其系统表空间中存储多个表,
并且数据文件时间戳不适用。即使使用
单独文件中的
每个表的
文件每表模式,
更改缓冲,也会使用数据文件时间戳; 但是,在Windows上,时间戳不会被更新更新,因此该值不准确。
InnoDB.ibd也会延迟写入数据文件,因此文件修改时间与最后一次插入,更新或删除的时间不同。对于
MyISAM
Check_time
表格最后一次被检查时。并非所有存储引擎都会进行更新,在这种情况下,该值始终存在
NULL。
Collation
表格的字符集和整理。
Checksum
现场校验和值(如果有的话)。
Create_options
额外的选项使用CREATE
TABLE。CREATE TABLE调用时提供的原始选项
将保留,此处报告的选项可能与活动表格设置和选项不同。
Comment
创建表时使用的注释(或者为什么MySQL无法访问表信息的信息)。
备注:
对于MEMORY表,
Data_length,
Max_data_length,和
Index_length值近似分配内存的实际数量。分配算法大量地预留内存以减少分配操作的数量。
对于视图,所显示的所有字段
SHOW TABLE STATUS都
NULL只是Name
表示视图名称和Comment说
view。
显示[全部]表格
[{FROM | IN} db_name]
[LIKE' pattern'| WHERE expr]
SHOW TABLES列出TEMPORARY给定数据库中的非表。你也可以使用mysqlshow
db_name命令获得这个列表。该
LIKE子句(如果存在)指示要匹配哪些表名。如第24.34节“对SHOW语句的扩展”中WHERE所讨论的,可以使用该子句使用更一般的条件来选择行。
该LIKE子句执行的匹配取决于lower_case_table_names系统变量的设置
。
该语句还列出了数据库中的所有视图。可选FULL修饰符会导致
SHOW TABLES显示第二个输出列,其中BASE TABLE包含表格和VIEW视图的值。
如果您没有对基表或视图的权限,则它不会显示在SHOW
TABLES或mysqlshow db_name的输出中。
SHOW TRIGGERS
[{FROM | IN} db_name]
[LIKE' pattern'| WHERE expr]
SHOW TRIGGERS列出当前为数据库中的表定义的触发器(缺省数据库,除非FROM给出子句)。此语句仅返回您有权访问的数据库和表的结果TRIGGER
。该LIKE子句(如果存在)指示要匹配哪些表名(而不是触发器名),并使语句显示这些表的触发器。如第24.34节“对SHOW语句的扩展”中WHERE所讨论的,可以使用该子句使用更一般的条件来选择行
。
对于第23.3节“使用触发器”中ins_sum定义的
触发器,此语句的输出如下所示:
MySQL的> SHOW TRIGGERS LIKE 'acc%'\G
*************************** 1. row ******************** *******
触发器:ins_sum
事件:插入
表格:帐户
声明:SET @sum = @sum + NEW.amount
时机:之前
创建于:2013-07-09 10:39:34.96
sql_mode:NO_ENGINE_SUBSTITUTION
定义者:我@本地主机
character_set_client:utf8
collation_connection:utf8_general_ci
数据库整理:latin1_swedish_ci
SHOW TRIGGERS 输出具有以下列:
Trigger:触发器名称。
Event:导致触发器激活的操作类型。值是
'INSERT','UPDATE',或
'DELETE'。
Table:定义触发器的表格。
Statement:触发体; 即触发器激活时执行的语句。
Timing:在触发事件之前还是之后激活触发器。值是
'BEFORE'或'AFTER'。
Created:触发器创建的日期和时间。TIMESTAMP(2)对于在5.7.2或更高版本中NULL创建的触发器,对于5.7.2之前创建的触发器,这是一个
值(以百分之一秒为单位)。
sql_mode:触发器执行时有效的SQL模式。
Definer:以
格式创建触发器的用户的帐户
。
'user_name'@'host_name'
character_set_client:character_set_client
创建触发器时的系统变量的会话值。
collation_connection:collation_connection
创建触发器时的系统变量的会话值。
Database Collation:与触发器关联的数据库的归类。
您还可以从中获取有关触发器对象的信息
INFORMATION_SCHEMA,其中包含一个
TRIGGERS表。请参见
第24.28节“INFORMATION_SCHEMA触发器表”。
SHOW [GLOBAL | SESSION] VARIABLES
[LIKE' pattern'| WHERE expr]
从MySQL 5.7.6开始,show_compatibility_56系统变量的值
影响这里描述的语句所需的信息和所需的权限。有关详细信息,请参见第5.1.5节“服务器系统变量”中对该变量的描述
。
SHOW VARIABLES显示MySQL系统变量的值(参见
第5.1.5节“服务器系统变量”)。该声明不需要任何特权。它只需要连接到服务器的能力。
系统变量信息也可以从这些来源获得:
对于SHOW VARIABLES,一个
LIKE子句(如果存在)指示要匹配哪些变量名称。如第24.34节“SHOW语句的扩展”中WHERE所讨论的,可以使用一个子句来使用更一般的条件来选择行。
SHOW VARIABLES接受可选GLOBAL或SESSION
可变范围修改器:
使用GLOBAL修饰符,该语句显示全局系统变量值。这些是用于为与MySQL的新连接初始化相应会话变量的值。如果变量没有全局值,则不显示任何值。
使用SESSION修饰符,该语句显示当前连接有效的系统可变值。如果变量没有会话值,则显示全局值。LOCAL是一个同义词SESSION。
如果不存在修饰符,则默认为
SESSION。
第5.1.5节“服务器系统变量” 列出了每个系统变量的作用域 。
SHOW VARIABLES受限于版本相关的显示宽度限制。对于非常长的值未完全显示的变量,请将其
SELECT用作解决方法。例如:
SELECT @@ GLOBAL.innodb_data_file_path;
大多数系统变量可以在服务器启动时设置(只读变量,例如
version_comment异常)。这些SET
语句可以在运行时更改许多
。请参见第5.1.6节“使用系统变量”和
第13.7.4.1节“变量赋值的SET语法”。
部分输出显示在这里。您的服务器的名称和值列表可能会有所不同。 第5.1.5节“服务器系统变量”描述了每个变量的含义,第5.1.1节“配置服务器”提供了有关调整它们的信息。
MySQL的> SHOW VARIABLES;
+ ----------------------------------------- + ------- -------------------- +
| 变量名| 值|
+ ----------------------------------------- + ------- -------------------- +
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| 自动提交| ON |
| automatic_sp_privileges | ON |
| back_log | 50 |
| basedir | /home/jon/bin/mysql-5.5 |
| big_tables | OFF |
| binlog_cache_size | 32768 |
| binlog_direct_non_transactional_updates | OFF |
| binlog_format | 声明|
| binlog_stmt_cache_size | 32768 |
| bulk_insert_buffer_size | 8388608 |
...
| max_allowed_packet | 4194304 |
| max_binlog_cache_size | 18446744073709547520 |
| max_binlog_size | 1073741824 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
| max_connect_errors | 100 |
| max_connections | 151 |
| max_delayed_threads | 20 |
| max_error_count | 64 |
| max_heap_table_size | 16777216 |
| max_insert_delayed_threads | 20 |
| max_join_size | 18446744073709551615 |
...
| thread_handling | 单线程连接|
| thread_stack | 262144 |
| time_format | %H:%i:%s |
| time_zone | SYSTEM |
| 时间戳| 1316689732 |
| tmp_table_size | 16777216 |
| tmpdir | / tmp |
| transaction_alloc_block_size | 8192 |
| transaction_isolation | 可重复阅读|
| transaction_prealloc_size | 4096 |
| transaction_read_only | OFF |
| tx_isolation | 可重复阅读|
| tx_read_only | OFF |
| unique_checks | ON |
| updatable_views_with_limit | 是|
| 版本| 5.5.17-log |
| version_comment | 来源分布|
| version_compile_machine | x86_64 |
| version_compile_os | Linux |
| wait_timeout | 28800 |
| warning_count | 0 |
+ ----------------------------------------- + ------- -------------------- +
使用LIKE子句时,语句仅显示那些名称与模式匹配的变量的行。要获取特定变量的行,请使用LIKE如下所示的
子句:
SHOW VARIABLES LIKE'max_join_size'; SHOW SESSION VARIABLES like'max_join_size';
要获取名称与模式匹配的变量列表,请%在LIKE子句中使用
通配符
:
SHOW VARIABLES LIKE'%size%'; 显示全局变量,如'%size%';
通配符可以在要匹配的模式中的任何位置使用。严格地说,因为_是一个匹配任何单个字符的通配符,所以
您应该将其转义为\_与字面匹配。在实践中,这很少需要。
SHOW WARNINGS [LIMIT [offset,]row_count] 显示计数(*)警告
SHOW WARNINGS是一个诊断语句,显示有关在当前会话中执行语句所产生的条件(错误,警告和注释)的信息。针对DML语句(如INSERT,
UPDATE和
LOAD DATA
INFILE)以及DDL语句(如
CREATE TABLE和)
生成警告ALTER TABLE。
该LIMIT子句与语句的语法相同SELECT。请参见
第13.2.9节“SELECT语法”。
SHOW WARNINGS以下也用于EXPLAIN显示由生成的扩展信息
EXPLAIN。请参见
第8.8.3节“扩展EXPLAIN输出格式”。
SHOW WARNINGS显示有关在当前会话中执行最新的非诊断性语句所导致的状况的信息。如果最近的语句在解析过程中导致错误,则
SHOW WARNINGS显示结果条件,而不管语句类型(诊断或不诊断)。
该SHOW COUNT(*)
WARNINGS诊断语句显示错误,警告和注意事项的总数。您也可以从warning_count系统变量中检索这个数字
:
显示计数(*)警告; SELECT @@ warning_count;
这些陈述的不同之处在于,第一个是没有清除消息列表的诊断语句。第二,因为它是一个SELECT
声明被认为是不可诊断的,并且清除消息列表。
相关的诊断语句SHOW
ERRORS仅显示错误条件(不包括警告和注释),
SHOW COUNT(*)
ERRORS语句显示错误的总数。请参见第13.7.5.17节“SHOW ERRORS Syntax”。GET
DIAGNOSTICS可以用来检查个别条件的信息。请参见第13.6.7.3节“GET DIAGNOSTICS语法”。
以下是一个简单的示例,显示以下数据转换警告
INSERT:
MySQL的>CREATE TABLE t1 (a TINYINT NOT NULL, b CHAR(4));查询OK,0行受影响(0.05秒) MySQL的>INSERT INTO t1 VALUES(10,'mysql'), (NULL,'test'), (300,'xyz');查询OK,3行受影响,3个警告(0.00秒) 记录:3重复:0警告:3 MySQL的>SHOW WARNINGS\G*************************** 1. row ******************** ******* 级别:警告 代码:1265 消息:数据在第1行的列'b'被截断 *************************** 2. row ******************** ******* 级别:警告 代码:1048 消息:列'a'不能为空 *************************** 3. row ******************** ******* 级别:警告 代码:1264 消息:第3行的列“a”超出范围值 设置3行(0.00秒)
所述max_error_count系统变量控制错误,警告和音符信息的最大数量的量,服务器存储的信息,因此该消息数SHOW
WARNINGS显示。要更改服务器可以存储的消息数量,请更改其值
max_error_count。默认值是64。
max_error_count只控制存储多少条消息,而不控制多少条消息。即使生成的消息数量超过warning_count了max_error_count,
该值也不受限制max_error_count。以下示例演示了这一点。该ALTER
TABLE语句会生成三条警告消息(严格的SQL模式在示例中被禁用,以防止单个转换问题后发生错误)。只有一条消息被存储并显示,因为
max_error_count已经被设置为1,但是所有三条都被计数(如由值所示
warning_count):
MySQL的>SHOW VARIABLES LIKE 'max_error_count';+ ----------------- + ------- + | 变量名| 值| + ----------------- + ------- + | max_error_count | 64 | + ----------------- + ------- + 一排(0.00秒) MySQL的>SET max_error_count=1, sql_mode = '';查询OK,0行受影响(0.00秒) MySQL的>ALTER TABLE t1 MODIFY b CHAR;查询OK,3行受影响,3个警告(0.00秒) 记录:3重复:0警告:3 MySQL的>SHOW WARNINGS;+ --------- + ------ + -------------------------------- -------- + | 级别| 代码| 留言| + --------- + ------ + -------------------------------- -------- + | 警告| 1263 | 数据在第1行的列'b'被截断 + --------- + ------ + -------------------------------- -------- + 一排(0.00秒) MySQL的>SELECT @@warning_count;+ ----------------- + | @@ warning_count | + ----------------- + | 3 | + ----------------- + 一排(0.01秒)
要禁用消息存储,请将其设置
max_error_count为0.在此情况下,warning_count仍指示发生了多少次警告,但消息未存储并且无法显示。
该sql_notes系统变量控制是否说明消息增量
warning_count和服务器是否将它们存储。默认情况下
sql_notes为1,但如果设置为0,则笔记不会增加
warning_count,并且服务器不存储它们:
mysql>SET sql_notes = 1;mysql>DROP TABLE IF EXISTS test.no_such_table;查询确定,0行受影响,1个警告(0.00秒) MySQL的>SHOW WARNINGS;+ ------- + ------ + ---------------------------------- - + | 级别| 代码| 留言| + ------- + ------ + ---------------------------------- - + | 注意| 1051 | 未知表'test.no_such_table'| + ------- + ------ + ---------------------------------- - + 一排(0.00秒) mysql>SET sql_notes = 0;mysql>DROP TABLE IF EXISTS test.no_such_table;查询OK,0行受影响(0.00秒) MySQL的>SHOW WARNINGS;空集(0.00秒)
MySQL服务器向每个客户端发送一个计数,指示由该客户端执行的最新语句产生的错误,警告和注释的总数。在C API中,这个值可以通过调用获得
mysql_warning_count()。请参见
第27.8.7.78节“mysql_warning_count()”。
在MySQL的客户端,可以启用和禁用使用自动警告显示
warnings和nowarning
分别的命令,或它们的快捷方式,
\W以及\w(参见
第4.5.1.2节“MySQL的命令”)。例如:
MySQL的>\W显示警告启用。 MySQL的>SELECT 1/0;+ ------ + | 1/0 | + ------ + | NULL | + ------ + 1行,1警告(0.03秒) 警告(代码1365):除以0 MySQL的>\w显示禁用的警告。
BINLOG' str'
BINLOG是内部使用声明。它由mysqlbinlog
程序生成,作为二进制日志文件中某些事件的可打印表示。(请参见第4.6.7节“ mysqlbinlog - 处理二进制日志文件的实用程序”。)该
值是该服务器解码的基本64编码字符串,用于确定由相应事件指示的数据更改。该声明需要特权。
'str'SUPER
该语句只能执行格式描述事件和行事件。
CACHE INDEXtbl_index_list[,tbl_index_list] ... [PARTITION(partition_list| ALL)] 在key_cache_nametbl_index_list:tbl_name[[INDEX | KEY](index_name[,index_name] ...)]partition_list:partition_name[,partition_name] [,...]
该CACHE INDEX语句将表索引分配给特定的键缓存。它仅用于
MyISAM表格。索引分配后,如果需要,可以将它们预加载到缓存中
LOAD INDEX INTO
CACHE。
下面的语句从表中分配指标
t1,t2以及
t3名为键缓存
hot_cache:
MySQL的> CACHE INDEX t1, t2, t3 IN hot_cache;
+ --------- + -------------------- + ---------- + ------- --- +
| 表| 操作| Msg_type | Msg_text |
+ --------- + -------------------- + ---------- + ------- --- +
| test.t1 | assign_to_keycache | 状态| 好的|
| test.t2 | assign_to_keycache | 状态| 好的|
| test.t3 | assign_to_keycache | 状态| 好的|
+ --------- + -------------------- + ---------- + ------- --- +
语法CACHE INDEX使您能够指定只有来自表的特定索引应分配给缓存。当前实现将所有表的索引分配给缓存,因此没有理由指定除表名之外的任何其他内容。
CACHE
INDEX语句中
引用的键缓存可以通过使用参数设置语句或在服务器参数设置中设置其大小来创建。例如:
MySQL的> SET GLOBAL keycache1.key_buffer_size=128*1024;
密钥缓存参数可以作为结构化系统变量的成员进行访问。请参见 第5.1.6.1节“结构化系统变量”。
在为其分配索引之前,密钥缓存必须存在:
MySQL的> CACHE INDEX t1 IN non_existent_cache;
错误1284(HY000):未知密钥缓存'non_existent_cache'
默认情况下,表索引分配给在服务器启动时创建的主(默认)键缓存。当关键缓存被破坏时,分配给它的所有索引将再次分配给默认键缓存。
索引分配会全局影响服务器:如果一个客户端将索引分配给给定缓存,则无论哪个客户端发出查询,该缓存都将用于涉及索引的所有查询。
在MySQL 5.7中,这个语句也支持分区MyISAM表。您可以将一个,多个或所有分区的一个或多个索引分配给给定的键缓存。例如,您可以执行以下操作:
CREATE TABLE pt(c1 INT,c2 VARCHAR(50),INDEX i(c1))
ENGINE = MyISAM数据
HASH分区(c1)
分区4;
SET GLOBAL kc_fast.key_buffer_size = 128 * 1024;
SET GLOBAL kc_slow.key_buffer_size = 128 * 1024;
CACHE INDEX pt PARTITION(p0)IN kc_fast;
CACHE INDEX pt PARTITION(p1,p3)IN kc_slow;
前一组语句执行以下操作:
创建一个带有4个分区的分区表; 这些分区自动命名p0,...... p3; 此表有一个名为i列的索引
c1。
创建两个名为kc_fastand的
键缓存kc_slow
分配为分区的索引p0的
kc_fast键缓存和用于分区的索引p1和p3
到kc_slow键缓存; 剩余分区(p2)的索引使用服务器的默认键缓存。
如果您希望将表中所有分区的索引分配给指定的pt单个键缓存
kc_all,则可以使用以下两种语句之一:
CACHE INDEX pt PARTITION(ALL)IN kc_all; CACHE INDEX pt IN kc_all;
刚才显示的两个陈述是等同的,发布其中一个具有完全相同的效果。换句话说,如果您希望将分区表的所有分区的索引分配给相同的键缓存,则该PARTITION
(ALL)子句是可选的。
将多个分区的索引分配给密钥缓存时,分区不必是连续的,并且不需要按任何特定顺序列出其名称。未明确分配给密钥缓存的任何分区的索引自动使用服务器的默认密钥缓存。
在MySQL 5.7中,分区MyISAM表也支持索引预加载。有关更多信息,请参见第13.7.6.5节“LOAD INDEX INTO CACHE语法”。
FLUSH [NO_WRITE_TO_BINLOG | LOCAL] {
flush_option[,flush_option] ...
| tables_option
}
flush_option:{
二进制日志
| DES_KEY_FILE
| 发动机记录
| 错误日志
| 通用日志
| HOSTS
| 日志
| 特权
| OPTIMIZER_COSTS
| QUERY CACHE
| 继电器记录[用于通道channel]
| 慢日志
| 状态
| USER_RESOURCES
}
tables_option:{
TABLES
| TABLES tbl_name[,tbl_name] ...
| 有读锁的表
| TABLES tbl_name[,tbl_name] ...带有读锁
| 表格tbl_name[,tbl_name] ...用于出口
}
该FLUSH语句有几种变体形式,用于清除或重新加载各种内部缓存,刷新表或获取锁。要执行
FLUSH,您必须有
RELOAD权限。如后面所述,特定的刷新选项可能需要额外的权限。
无法FLUSH在存储的函数或触发器中发布
语句。但是,您可以FLUSH在存储过程中使用
,只要这些不从存储函数或触发器中调用。参见第C.1节“对存储程序的限制”。
默认情况下,服务器将FLUSH语句写入
二进制日志,以便它们复制到复制从服务器。要禁止日志记录,请指定可选
NO_WRITE_TO_BINLOG关键字或其别名
LOCAL。
FLUSH LOGS,
FLUSH TABLES WITH READ LOCK
(有或没有表列表),并且
在任何情况下都不会写入二进制日志,因为如果复制到从属服务器会导致问题。
FLUSH
TABLES tbl_name ... FOR
EXPORT
该FLUSH语句会导致隐式提交。请参见第13.3.3节“导致隐式提交的语句”。
所述中mysqladmin实用程序提供了一个命令行界面一些刷新操作,使用诸如命令flush-hosts,
flush-logs,
flush-privileges,
flush-status,和
flush-tables。请参见
第4.5.2节“ mysqladmin - 管理MySQL服务器的客户端”。
向SIGHUP服务器发送信号会导致发生几次类似于各种形式FLUSH语句的刷新操作。请参见
第5.1.12节“服务器对信号的响应”。
该RESET声明与之类似
FLUSH。有关在复制中使用语句的信息
,请参见
第13.7.6.6节“RESET语法”RESET。
以下列表描述了允许的
FLUSH语句
flush_option值。有关FLUSH
TABLES变体的说明,请参阅
FLUSH TABLES语法。
关闭并重新打开服务器正在写入的任何二进制日志文件。如果启用二进制日志记录,则二进制日志文件的序列号会相对于前一个文件增加1。
从--des-key-file服务器启动时使用该选项指定的文件重新加载DES密钥。
这些DES_ENCRYPT()和
DES_DECRYPT()函数从MySQL 5.7.6开始不推荐使用,将在未来的MySQL版本中被删除,不应再使用。因此,
--des-key-file并
DES_KEY_FILE也已过时,将被删除。
关闭并重新打开安装的存储引擎的任何可冲刷日志。这会导致InnoDB将日志刷新到磁盘。
关闭并重新打开服务器正在写入的任何错误日志文件。
关闭并重新打开服务器正在写入的任何常规查询日志文件。
清空主机缓存。如果某些主机更改了IP地址,或者来自合法主机的连接发生了错误消息,请刷新主机缓存
。(请参见第B.5.2.5节“主机'host_name'被阻止”。)超过时
Host 'host_name' is
blockedmax_connect_errors连接到MySQL服务器时,给定主机连续发生错误时,MySQL会认为出现问题并阻止主机进一步连接请求。刷新主机缓存可启用主机的更多连接尝试。默认值为
max_connect_errors100.要避免此错误消息,请将服务器
max_connect_errors设置为较大的值。
关闭并重新打开服务器正在写入的任何日志文件。如果启用二进制日志记录,则二进制日志文件的序列号会相对于前一个文件增加1。如果启用中继日志记录,则中继日志文件的序列号会相对于前一个文件增加1。
FLUSH LOGS 对用于常规查询日志或慢查询日志的表没有影响(请参阅 第5.4.1节“选择常规查询和慢查询日志输出目标”)。
重新读取成本模型表,以便优化器开始使用存储在其中的当前成本估算值。服务器向错误日志中写入任何无法识别的条目的警告。(有关这些表格的信息,请参阅 第8.9.5节“优化器成本模型”。)此操作仅影响在刷新后开始的会话。现有会议继续使用开始时的当前成本估算。
重新加载mysql系统数据库中授予表的权限
。
服务器在内存中缓存信息的结果
GRANT,
CREATE USER,
CREATE SERVER,和
INSTALL PLUGIN语句。该内存不能由相应的释放
REVOKE,
DROP USER,
DROP SERVER,和
UNINSTALL PLUGIN语句,所以执行导致缓存报表的多个实例的服务器上,将有内存使用的增加。这个缓存的内存可以被释放
FLUSH PRIVILEGES。
对查询缓存进行碎片整理以更好地利用其内存。
FLUSH QUERY CACHE不从缓存中删除任何疑问,不像
FLUSH TABLES或
RESET QUERY CACHE。
查询缓存从MySQL 5.7.20开始已弃用,并在MySQL 8.0中删除。弃用包括
FLUSH QUERY CACHE。
FLUSH
RELAY LOGS [FOR CHANNEL
channel]
关闭并重新打开服务器正在写入的任何中继日志文件。如果启用中继日志记录,则中继日志文件的序列号会相对于前一个文件增加1。
该子句使您能够命名该语句适用于哪个复制通道。执行
以刷新特定复制通道的中继日志。如果没有通道被命名并且不存在额外的复制通道,则该语句适用于默认通道。如果没有命名通道并且存在多个复制通道,则该语句适用于所有复制通道。有关更多信息,请参见第16.2.3节“复制通道”。
FOR CHANNEL
channelFLUSH
RELAY LOGS FOR CHANNEL
channel
关闭并重新打开服务器正在写入的任何慢速查询日志文件。
show_compatibility_56
系统变量
的值
会影响此选项的操作。有关详细信息,请参见第5.1.5节“服务器系统变量”中对该变量的描述
。
该选项将当前线程的会话状态变量值添加到全局值,并将会话值重置为零。一些全局变量也可以重置为零。它还会将密钥缓存的计数器(默认和已命名)重置为零,并设置
Max_used_connections为当前打开的连接数。调试查询时可能会使用此信息。请参见
第1.7节“如何报告错误或问题”。
将所有每小时用户资源重置为零。这使已达到每小时连接,查询或更新限制的客户端立即恢复活动。
FLUSH USER_RESOURCES不适用于由max_user_connections系统变量控制的最大同时连接限制
。请参见第6.3.5节“设置帐户资源限制”。
FLUSH TABLES刷新表格,并根据使用的变体获取锁定。声明中TABLES使用的任何
变体
FLUSH必须是唯一使用的选项。FLUSH
TABLE是一个同义词FLUSH
TABLES。
这里的描述表明通过关闭它们来刷新表格会有不同的应用InnoDB,这会将表格内容刷新到磁盘上,但会使其打开。这仍然允许表格文件在表格打开时被复制,只要其他活动不修改它们即可。
关闭所有打开的表,强制所有正在使用的表被关闭,并刷新查询缓存和准备语句缓存。FLUSH TABLES也会从查询缓存中删除所有查询结果,如
RESET QUERY CACHE语句。有关查询缓存和预备语句缓存的信息,请参见第8.10.3节“MySQL查询缓存”。和
第8.10.4节“缓存已准备好的陈述和存储的程序”。
FLUSH TABLES当有活动时不允许
LOCK TABLES ...
READ。要刷新和锁定表,请改为使用
。
FLUSH
TABLES tbl_name ... WITH READ
LOCK
FLUSH
TABLES
tbl_name [,
tbl_name] ...
用一个或多个以逗号分隔的表名列表,这个语句就像FLUSH
TABLES没有名字,除了服务器只刷新指定的表。如果命名表不存在,则不会发生错误。
关闭所有打开的表并锁定全局读取锁定的所有数据库的所有表。如果您拥有可以及时拍摄快照的文件系统(如Veritas或ZFS),则这是一种非常方便的备份方式。使用
UNLOCK
TABLES即可解除锁定。
FLUSH TABLES WITH READ LOCK
获得全局读锁定,而不是表锁,所以它不会受到相同的行为
LOCK TABLES,并
UNLOCK
TABLES相对于表锁定和隐式的提交:
UNLOCK
TABLES只有当前任何表已被锁定时才隐含地提交任何活动事务LOCK TABLES。提交不会发生
UNLOCK
TABLES跟随,FLUSH
TABLES WITH READ LOCK因为后者的语句不会获取表锁。
开始一个事务会导致获取的表锁
LOCK TABLES被释放,就好像你已经执行了一样
UNLOCK
TABLES。开始一个事务不会释放一个全局读取锁
FLUSH TABLES WITH READ
LOCK。
FLUSH TABLES WITH READ LOCK
与XA交易不兼容。
FLUSH TABLES WITH READ LOCK
不会阻止服务器将行插入日志表(请参见第5.4.1节“选择常规查询和慢速查询日志输出目标”)。
FLUSH
TABLES
tbl_name [,
tbl_name] ... WITH READ
LOCK
该语句刷新并获取指定表的读锁。该语句首先获取这些表的独占元数据锁,因此它会等待这些表打开的事务完成。然后,语句清除表缓存中的表,重新打开表,获取表锁(例如
LOCK TABLES ...
READ),并将元数据锁从独占式降级到共享式。在语句获取锁并降级元数据锁之后,其他会话可以读取但不能修改表。
由于此语句获取表锁,LOCK TABLES除了RELOAD使用任何表所需的特权之外,您还必须拥有每个表的
特权FLUSH
语句。
这个语句只适用于现有的基本TEMPORARY) 表(非表,如果一个名称引用了一个基表,则使用该TEMPORARY表,如果引用了一个
表,则忽略它;如果一个名称适用于视图,
ER_WRONG_OBJECT则会发生错误。 ,发生
ER_NO_SUCH_TABLE错误。
使用UNLOCK
TABLES释放锁,
LOCK TABLES以释放锁和收购其他的锁,或
START
TRANSACTION释放锁,并开始一个新的事务。
该FLUSH TABLES变体使表可以在单个操作中刷新并锁定。它提供了一种解决方法,用于FLUSH TABLES在存在活动时不允许
的限制
LOCK TABLES ...
READ。
该语句不会执行隐式操作
UNLOCK
TABLES,因此如果在有任何活动时使用该语句,LOCK TABLES或者第二次使用该语句而没有首先释放获取的锁,则会导致错误
。
如果一个冲刷的桌子被打开
HANDLER,处理程序将被隐式刷新并丢失其位置。
FLUSH
TABLES
tbl_name [,
tbl_name] ... FOR
EXPORT
这个FLUSH TABLES变体适用于InnoDB表格。它确保对指定表的更改已刷新到磁盘,以便在服务器运行时可以创建二进制表副本。
声明如下所示:
它获取指定表的共享元数据锁。只要其他会话具有修改这些表或为其保存表锁的活动事务,语句就会阻塞。在获取锁之后,语句会阻止尝试更新表的事务,同时允许只读操作继续。
它检查表中的所有存储引擎是否支持FOR EXPORT。如果有,
ER_ILLEGAL_HA则会发生错误并且语句失败。
该声明通知存储引擎为每个表格准备导出表格。存储引擎必须确保将任何挂起的更改写入磁盘。
该语句将会话置于锁表模式,以便在FOR EXPORT
语句完成时不会释放先前获取的元数据锁定。
该
FLUSH
TABLES ... FOR EXPORT声明要求您拥有SELECT每个表的特权。由于此语句获取表锁,LOCK
TABLES除了RELOAD使用任何FLUSH
语句所需的特权之外,您还必须拥有每个表的特权。
此声明仅适用于现有的基(非TEMPORARY)表。如果名称引用基表,则使用该表。如果它引用一个
TEMPORARY表格,它将被忽略。如果名称适用于视图,
ER_WRONG_OBJECT则会发生错误。否则,
ER_NO_SUCH_TABLE会发生错误。
InnoDB支持FOR
EXPORT具有自己的
.ibd
文件文件的表(也就是在innodb_file_per_table
启用该设置的情况下创建的表
)。InnoDB确保通过FOR EXPORT声明通知任何更改已刷新到磁盘。这允许在FOR
EXPORT语句有效时创建表内容的二进制副本,因为该
.ibd文件是事务一致的,并且可以在服务器运行时进行复制。FOR
EXPORT不适用于InnoDB
系统表空间文件或InnoDB
具有FULLTEXT索引的表。
FLUSH
TABLES ...FOR EXPORT分区InnoDB表支持
。
通知时FOR EXPORT,
InnoDB写入磁盘的某些类型的数据通常保存在内存中或表空间文件外部的单独磁盘缓冲区中。对于每个表,
InnoDB还会生成
与该表在同一数据库目录中命名的文件
。该
table_name.cfg.cfg文件包含稍后将表空间文件重新导入到相同或不同服务器所需的元数据。
当FOR EXPORT语句完成时,
InnoDB将所有脏页面刷新
到表格数据文件。任何
更改缓冲区
条目在刷新之前被合并。此时,表被锁定并静止:表在磁盘上处于事务一致状态,您可以复制.ibd表空间文件以及相应的.cfg文件以获得这些表的一致快照。
有关将复制的表数据重新导入到MySQL实例的过程,请参见第14.7.6节“将文件 - 表 - 表空间复制到另一个实例”。
完成表后,使用
UNLOCK
TABLES释放锁,
LOCK TABLES释放锁并获取其他锁,或
START
TRANSACTION释放锁并开始新的事务。
虽然任何这些陈述在会话中都有效,但尝试使用会
FLUSH
TABLES ... FOR EXPORT产生错误:
FLUSH TABLES ...带有读锁 FLUSH TABLES ...出口 LOCK TABLES ... READ 锁表...写
虽然
FLUSH
TABLES ... FOR EXPORT在会话中有效,但试图使用这些语句中的任何一个都会产生错误:
带读锁的冲刷表 FLUSH TABLES ...带有读锁 FLUSH TABLES ...出口
杀死[连接| QUERY]processlist_id
到mysqld的每个连接都在一个单独的线程中运行。你可以用语句杀死一个线程。
KILL
processlist_id
螺纹PROCESSLIST标识符可以从被确定
ID的列
INFORMATION_SCHEMA.PROCESSLIST
表,所述Id的列
SHOW PROCESSLIST输出,并且
PROCESSLIST_ID性能架构的列threads表。当前线程的值由CONNECTION_ID()函数返回
。
KILL允许一个可选
CONNECTION或QUERY
修饰符:
KILL
CONNECTIONKILL与没有修饰符相同
:processlist_id在终止任何连接执行的语句之后,它终止与给定关联
的连接。
KILL QUERY
终止连接当前正在执行的语句,但保持连接本身完好无损。
如果您有PROCESS
权限,则可以看到所有主题。如果您有
SUPER权限,则可以杀死所有线程和语句。否则,你只能看到并杀死你自己的线程和语句。
您也可以使用mysqladmin processlist 和mysqladmin kill命令来检查和终止线程。
您不能KILL与嵌入式MySQL服务器库一起使用,因为嵌入式服务器仅在主机应用程序的线程内运行。它不创建任何自己的连接线程。
当你使用时KILL,为线程设置一个特定于线程的kill标志。在大多数情况下,线程可能需要一些时间才能死掉,因为kill标志只在特定的时间间隔被检查:
在SELECT操作期间,对于
ORDER BY和GROUP BY
循环,在读取一行数据块后检查该标志。如果设置了kill标志,语句会中止。
ALTER TABLE对于从原始表中读取的每几个复制行,进行表复制的操作会定期检查kill标志。如果设置了kill标志,语句会中止并删除临时表。
该KILL语句无需等待确认即可返回,但kill标志检查将在相当短的时间内中止操作。中止执行任何必要的清理操作也需要一些时间。
期间UPDATE或
DELETE操作,杀标志读取每个块之后和每个更新或删除的行之后检查。如果设置了kill标志,语句会中止。如果您未使用事务,则更改不会回滚。
GET_LOCK()中止并返回
NULL。
如果线程在表锁定处理程序(状态
Locked:)中,则表锁定会迅速中止。
如果线程正在等待写入调用中的可用磁盘空间,则写入操作会因“ 磁盘已满 ” 错误消息而中止。
在表上
杀死一个REPAIR TABLE或
一个OPTIMIZE TABLE操作会
MyISAM导致一个表损坏且不可用。对这样的表进行任何读取或写入操作都会失败,直到您再次优化或修复(无中断)为止。
将索引加载到缓存tbl_index_list[,tbl_index_list] ...tbl_index_list:tbl_name[PARTITION(partition_list| ALL)] [[INDEX | KEY](index_name[,index_name] ...)] [IGNORE LEAVES]partition_list:partition_name[,partition_name] [,...]
该LOAD INDEX INTO
CACHE语句通过显式CACHE INDEX语句将键索引预加载到键缓存中,或者将键索引预加载
到默认键缓存中。
LOAD INDEX INTO
CACHE仅用于MyISAM
表格。在MySQL 5.7中,它也支持分区MyISAM表; 另外,分区表上的索引可以预先加载一个,多个或所有分区。
该IGNORE LEAVES修饰符只会导致索引的非叶节点的块被预加载。
IGNORE LEAVES也支持分区MyISAM表。
以下语句为表t1和索引预加载索引的节点(索引块)t2:
MySQL的> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+ --------- + -------------- + ---------- + ---------- +
| 表| 操作| Msg_type | Msg_text |
+ --------- + -------------- + ---------- + ---------- +
| test.t1 | preload_keys | 状态| 好的|
| test.t2 | preload_keys | 状态| 好的|
+ --------- + -------------- + ---------- + ---------- +
该语句预加载所有索引块
t1。它仅预装来自非叶节点的块t2。
语法LOAD
INDEX INTO CACHE使您能够指定仅预先加载表中的特定索引。当前实现将所有表索引预加载到缓存中,因此没有理由指定除表名之外的任何其他内容。
在MySQL 5.7中,可以在分区MyISAM
表的特定分区上预加载索引。例如,在以下两个语句中,第一个预加载索引用于p0分区表的分区pt,第二个预加载分区p1和
p3同一个表的索引:
LOAD INDEX INTO CACHE pt PARTITION(p0); LOAD INDEX INTO CACHE pt PARTITION(p1,p3);
要预加载表中所有分区的索引
pt,可以使用以下两种语句之一:
LOAD INDEX INTO CACHE pt PARTITION(ALL); LOAD INDEX INTO CACHE pt;
刚才显示的两个陈述是等同的,发布其中一个具有完全相同的效果。换句话说,如果您希望为分区表的所有分区预加载索引,那么该PARTITION (ALL)子句是可选的。
在预加载多个分区的索引时,分区不必是连续的,并且不需要按任何特定顺序列出其名称。
LOAD INDEX INTO
CACHE ... IGNORE LEAVES除非表中的所有索引具有相同的块大小,否则将失败。您可以使用myisamchk -dv并检查Blocksize列来确定表的索引块大小。
RESETreset_option[,reset_option] ...reset_option:{ 主 | QUERY CACHE | 奴隶 }
该RESET声明用于清除各种服务器操作的状态。您必须有权
RELOAD执行
RESET。
RESET作为FLUSH声明的更强版本。请参见
第13.7.6.3节“FLUSH语法”。
该RESET语句会导致隐式提交。请参见第13.3.3节“导致隐式提交的语句”。
在MySQL 5.7.1中,gtid_next必须设置为AUTOMATIC在发布此语句之前。这个限制不适用于MySQL 5.7.2或更高版本。(错误#16062608,错误#16715809,错误#69045)
以下列表描述了允许的
RESET语句
reset_option值:
RESET MASTER
删除索引文件中列出的所有二进制日志,将二进制日志索引文件重置为空,并创建一个新的二进制日志文件。
RESET QUERY CACHE
从查询缓存中删除所有查询结果。
查询缓存从MySQL 5.7.20开始已弃用,并在MySQL 8.0中删除。弃用包括
RESET QUERY
CACHE。
RESET SLAVE
使奴隶忘记其在主二进制日志中的复制位置。还通过删除任何现有的中继日志文件并重新开始新的中继日志来重置中继日志。
关掉
这个语句停止MySQL服务器。它需要
SHUTDOWN特权。
SHUTDOWN被添加到MySQL 5.7.9。它使用mysqladmin shutdown命令或
mysql_shutdown()C API函数为可用的相同功能提供SQL级别的接口。
该DESCRIBE和
EXPLAIN语句是同义词,或者用于获取有关表结构或查询执行计划的信息。有关更多信息,请参见
第13.7.5.5节“SHOW COLUMNS语法”和第13.8.2节“EXPLAIN语法”。
{EXPLAIN | 描述| DESC}
tbl_name[ col_name| wild]
{EXPLAIN | 描述| DESC}
[ explain_type]
{ explainable_stmt| FOR CONNECTION connection_id}
explain_type:{
EXTENDED
| PARTITIONS
| FORMAT =format_name
}
format_name:{
传统
| JSON
}
explainable_stmt:{
SELECT语句
| DELETE语句
| INSERT语句
| REPLACE语句
| UPDATE语句
}
该DESCRIBE和
EXPLAIN语句是同义词。在实践中,DESCRIBE关键字通常用于获取关于表结构的信息,而EXPLAIN用于获取查询执行计划(也就是说MySQL将如何执行查询)。
以下讨论
根据这些用途使用DESCRIBE和
EXPLAIN关键字,但MySQL解析器将它们视为完全同义。
DESCRIBE 提供有关表格中列的信息:
MySQL的> DESCRIBE City;
+ ------------ + ---------- + ------ + ------ + --------- + - -------------- +
| 字段| 类型| 空| Key | 默认| 额外|
+ ------------ + ---------- + ------ + ------ + --------- + - -------------- +
| Id | int(11)| NO | PRI | NULL | auto_increment |
| 名称| char(35)| NO | | | |
| 国家| char(3)| NO | UNI | | |
| 区| char(20)| 是| MUL | | |
| 人口| int(11)| NO | | 0 | |
+ ------------ + ---------- + ------ + ------ + --------- + - -------------- +
DESCRIBE是一个捷径
SHOW COLUMNS。这些声明还显示视图的信息。该描述
SHOW COLUMNS提供了有关输出列的更多信息。请参见
第13.7.5.5节“SHOW COLUMNS语法”。
默认情况下,DESCRIBE显示有关表中所有列的信息。
col_name如果给出,则是表中列的名称。在这种情况下,该语句仅显示指定列的信息。
wild,如果给出,是一个模式字符串。它可以包含SQL %和
_通配符。在这种情况下,该语句仅显示名称与字符串匹配的列的输出。除非包含空格或其他特殊字符,否则不需要将该字符串括在引号内。
该DESCRIBE声明是为了与Oracle兼容而提供的。
该SHOW CREATE TABLE,
SHOW TABLE STATUS和
SHOW INDEX声明还提供有关表格的信息。请参见第13.7.5节“SHOW语法”。
该EXPLAIN语句提供有关MySQL如何执行语句的信息:
当EXPLAIN与可解释的语句一起使用时,MySQL会显示来自优化器的关于语句执行计划的信息。也就是说,MySQL解释了它将如何处理该语句,包括有关表如何连接以及按何种顺序的信息。有关使用
EXPLAIN获取执行计划信息的信息,请参见第8.8.2节“EXPLAIN输出格式”。
当EXPLAIN与
可解释的语句一起使用时,它显示在命名连接中执行的语句的执行计划。请参见第8.8.4节“获取命名连接的执行计划信息”。
FOR CONNECTION
connection_id
对于SELECT语句,
EXPLAIN产生可以使用显示的附加执行计划信息
SHOW WARNINGS。请参见
第8.8.3节“扩展EXPLAIN输出格式”。
在较旧的MySQL版本中,使用扩展信息EXPLAIN
EXTENDED。该语法仍被认为是向后兼容的,但扩展输出现在默认启用,所以EXTENDED关键字是多余的并被弃用。它的使用会导致警告,并将其从EXPLAINMySQL 8.0中的语法中删除
。
EXPLAIN对于检查涉及分区表的查询很有用。请参见
第22.3.5节“获取有关分区的信息”。
在较老的MySQL版本中,分区信息是使用生成的
EXPLAIN
PARTITIONS。该语法仍被认为是向后兼容的,但分区输出现在默认启用,所以PARTITIONS关键字是多余的,并且已被弃用。它的使用会导致警告,并将其从EXPLAINMySQL 8.0中的语法中删除
。
该FORMAT选项可用于选择输出格式。TRADITIONAL以表格格式显示输出。如果没有FORMAT选项,这是默认值
。
JSON格式以JSON格式显示信息。
EXPLAIN需要SELECT访问任何表或视图的
权限,包括任何基础视图表。对于意见,EXPLAIN也需要
SHOW VIEW特权。
在帮助下EXPLAIN,您可以看到应该在哪里添加索引,以便通过使用索引查找行来更快地执行语句。您还可以
EXPLAIN用来检查优化程序是否以最佳顺序加入表。为了给优化器提示使用与SELECT语句中命名表的顺序相对应的连接顺序
,请使用SELECT STRAIGHT_JOIN而不是仅仅开始语句SELECT。(请参见
第13.2.9节“SELECT语法”。)
优化器跟踪有时可以提供与之相辅相成的信息EXPLAIN。但是,优化器跟踪格式和内容在版本之间可能会发生变化。有关详细信息,请参阅
MySQL内部:跟踪优化器。
如果您在确定索引时没有使用索引时遇到问题,请运行ANALYZE
TABLE以更新表格统计信息(如键的基数),这些索引可能会影响优化程序的选择。请参见
第13.7.2.1节“ANALYZE TABLE语法”。
MySQL Workbench具有Visual Explain功能,可提供EXPLAIN输出的可视表示
。请参阅
教程:使用说明来提高查询性能。
帮助' search_string'
该HELP语句返回MySQL参考手册中的在线信息。其正确的操作要求mysql
使用帮助主题信息初始化数据库中的帮助表(请参见
第5.1.11节“服务器端帮助”)。
该HELP语句在帮助表中搜索给定的搜索字符串并显示搜索结果。搜索字符串不区分大小写。
搜索字符串可以包含通配符
%和_。这些与操作员执行的模式匹配操作具有相同的含义
LIKE。例如,
HELP 'rep%'返回以开头的主题列表rep。
HELP语句理解几种类型的搜索字符串:
在最普通的级别,用于contents检索顶级帮助类别的列表:
帮助“内容”
有关给定帮助类别中的主题列表,例如
Data Types使用类别名称:
帮助“数据类型”
有关特定帮助主题(如
ASCII()函数或
CREATE TABLE语句)的帮助,请使用关联的一个或多个关键字:
帮助'ascii' 帮助'创建表'
换句话说,搜索字符串与类别,许多主题或单个主题相匹配。您无法预先告知给定的搜索字符串是否会返回单个帮助主题的项目列表或帮助信息。但是,您可以HELP通过检查结果集中的行数和列数来判断返回的响应类型。
以下说明指出结果集可以采用的表单。示例语句的输出使用您在使用mysql客户端时看到的熟悉的“ 表格 ”或“ 垂直 ”格式显示,但请注意,mysql本身以不同方式重新设置结果集的格式
。
HELP
空结果集
搜索字符串中找不到匹配项。
结果集包含具有三列的单行
这意味着搜索字符串对帮助主题产生了冲击。结果有三列:
name:主题名称。
description:该主题的描述性帮助文本。
example:使用示例或示例。此栏可能为空。
例: HELP 'replace'
产量:
名称:REPLACE
描述:语法:
REPLACE(STR,from_str均被,to_str)
返回所有出现的字符串from_str的字符串str
由字符串to_str取代。REPLACE()执行区分大小写
在搜索from_str时匹配。
例如:mysql> SELECT REPLACE('www.mysql.com','w','Ww');
- >'WwWwWw.mysql.com'
结果集包含具有两列的多行
这意味着搜索字符串与许多帮助主题相匹配。结果集指示帮助主题名称:
name:帮助主题名称。
is_it_category:Y如果名称表示帮助类别,N
则表示不支持。如果不是,则name指定为HELP
语句参数时的
值应产生包含指定项目说明的单行结果集。
例: HELP 'status'
产量:
+ ----------------------- + ---------------- + | 名称| is_it_category | + ----------------------- + ---------------- + | SHOW | N | | SHOW ENGINE | N | | SHOW MASTER STATUS | N | | SHOW PROCEDURE STATUS | N | | SHOW SLAVE STATUS | N | | 显示状态| N | | SHOW TABLE STATUS | N | + ----------------------- + ---------------- +
包含具有三列的多行的结果集
这意味着搜索字符串与一个类别匹配。结果集包含类别条目:
source_category_name:帮助类别名称。
name:类别或主题名称
is_it_category:Y如果名称表示帮助类别,N
则表示不支持。如果不是,则name指定为HELP
语句参数时的
值应产生包含指定项目说明的单行结果集。
例: HELP 'functions'
产量:
+ ---------------------- + ------------------------- + ---------------- + | source_category_name | 名称| is_it_category | + ---------------------- + ------------------------- + ---------------- + | 函数| CREATE FUNCTION | N | | 函数| 删除功能| N | | 函数| 位函数| Y | | 函数| 比较运算符| Y | | 函数| 控制流程功能| Y | | 函数| 日期和时间函数| Y | | 函数| 加密函数| Y | | 函数| 信息功能| Y | | 函数| 逻辑运算符| Y | | 函数| 杂项函数| Y | | 函数| 数字函数| Y | | 函数| 字符串函数| Y | + ---------------------- + ------------------------- + ---------------- +
使用 db_name
该
声明告诉MySQL将
数据库用作后续语句的默认(当前)数据库。在会话结束或另一个语句发布之前,数据库保持默认状态
:
USE db_namedb_nameUSE
使用db1; SELECT COUNT(*)FROM mytable; #从db1.mytable中选择 使用db2; SELECT COUNT(*)FROM mytable; #从db2.mytable中选择
通过USE语句使特定数据库成为缺省值
并不妨碍您访问其他数据库中的表。下面的示例访问author从表格
db1数据库和editor
从表db2数据库:
使用db1; SELECT author_name,editor_name FROM author,db2.editor WHERE author.editor_id = db2.editor.editor_id;